So I have this component
var LineItemRowsWrapper = React.createClass({
current_lineitem_count: 0,
getAjaxData: function(){
var lineitem_data = [];
for(var i = 0; i < this.current_lineitem_count; i++){
var data = this.refs['lineitem_'+i].getAjaxData();
lineitem_data.push(data)
}
return lineitem_data;
},
getLineitems: function(){
var self = this;
var lineitem_components = [];
this.current_lineitem_count = 0;
if(this.props.shoot){
var preview = this.props.preview;
var lineitems = this.props.shoot.get_lineitems();
lineitem_components = lineitems.map(function (item, index) {
var ref_str = 'lineitem_'+self.current_lineitem_count;
self.current_lineitem_count++;
return (
<LineItemRow item={item} key={index} ref={ref_str} preview={preview} onChange={self.props.onChange} />
)
});
}
return lineitem_components;
},
render: function() {
var lineitems = this.getLineitems();
return (
<div>
{lineitems}
</div>
)
}
})
the first time lineitems are rendered the refs work like expected. But if I add a lineitem to this.props.shoot the refs object of this component does not change.
So for example say I had an array of 3 lineitems
[i1,i2,i3]
this.refs would be
{lineitem_0:{}, lineitem_1:{}, lineitem_2:{}}
and when I update my lineitem array to be
[i1,i2,i3,i4]
this.refs does not change, it will still be
{lineitem_0:{}, lineitem_1:{}, lineitem_2:{}}
why doesn't the refs object update between renders? The LineItemRow components update properly so I know its not something wrong on that front. Any insights would be much appreciated!
____Edit____ (requested to add more code for context)
var DocumentContent = React.createClass({
contextTypes: {
router: React.PropTypes.func.isRequired
},
getParams: function(){
return this.context.router.getCurrentParams()
},
getInitialState: function() {
return {
shoot: ShootStore.get_shoot(this.getParams().shoot_id),
}
},
componentWillMount: function() {
ShootStore.bind( 'change', this.onStoreUpdate );
},
componentWillUnmount: function() {
ShootStore.unbind( 'change', this.onStoreUpdate );
},
onStoreUpdate: function(){
this.setState(this.getInitialState());
},
addLineItem: function() {
ShootActions.create_lineitem(this.state.shoot.id);
},
update_shoot_timeout: null,
update_shoot:function(){
var self = this;
window.clearTimeout(this.update_shoot_timeout)
this.update_shoot_timeout = window.setTimeout(function(){
var lineitem_data = self.refs.lineitems.getAjaxData()
if(self.props.shoot){
ShootActions.update_shoot(self.state.shoot.id, lineitem_data )
}
}, 500)
},
render: function() {
var shoot = this.state.shoot;
return (
<div className='document__content'>
<div className='row'>
<div className='document__expenses'>
<h3 className='lineitem__title'> Expenses </h3>
<LineItemRowsWrapper shoot={shoot} onChange={this.update_shoot} ref='lineitems'/>
</div>
<button onClick={this.addLineItem} className="btn-small btn-positive">
+ Add Expense
</button>
</div>
);
}
})
Under the section "Caution" in the react documentation about refs https://facebook.github.io/react/docs/more-about-refs.html
"Never access refs inside of any component's render method - or while any component's render method is even running anywhere in the call stack."
Which is exactly what you're doing.
Instead you should store state about the component in this.state
or properties of the component in this.props