Cha*_*aro 11 javascript render refs reactjs
所以我有这个组件
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>
)
}
})
Run Code Online (Sandbox Code Playgroud)
第一次使用lineitems渲染refs就像预期的那样工作.但是,如果我向this.props.shoot添加一个lineitem,则此组件的refs对象不会更改.
例如,假设我有一个包含3个lineitems的数组
[i1,i2,i3]
Run Code Online (Sandbox Code Playgroud)
this.refs会
{lineitem_0:{}, lineitem_1:{}, lineitem_2:{}}
Run Code Online (Sandbox Code Playgroud)
当我更新我的lineitem数组时
[i1,i2,i3,i4]
Run Code Online (Sandbox Code Playgroud)
this.refs不会改变,它仍然会改变
{lineitem_0:{}, lineitem_1:{}, lineitem_2:{}}
Run Code Online (Sandbox Code Playgroud)
为什么refs对象不能在渲染之间更新?LineItemRow组件正确更新,所以我知道它在前面没有错.任何见解将不胜感激!
____编辑_____(要求为上下文添加更多代码)
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>
);
}
})
Run Code Online (Sandbox Code Playgroud)
关于refs https://facebook.github.io/react/docs/more-about-refs.html的反应文档中的"警告"部分
"永远不要访问任何组件的render方法中的refs - 或者当任何组件的render方法甚至在调用堆栈中的任何地方运行时."
这正是你正在做的.
相反,您应该存储有关组件的状态this.state或组件的属性this.props
删除所有引用和迭代来读取数据。
应调用一直传递到 LineItem 组件的 onchange 处理程序,并仅传递发生更改的数据。(单个 LineItem 数据)
然后,通过状态处理 (DocumentContent) 在组件中对此进行处理。
创建一个操作 ShootActions.updateLineItem() 来更新商店中的相关订单项,然后发出更改并再次呈现所有内容。