【发布时间】:2015-06-04 09:11:33
【问题描述】:
所以我有这个组件
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>
)
}
})
第一次渲染 lineitems 时,refs 会像预期的那样工作。但是如果我向 this.props.shoot 添加一个 lineitem,这个组件的 refs 对象不会改变。
例如,假设我有一个包含 3 个 lineitems 的数组
[i1,i2,i3]
this.refs 将是
{lineitem_0:{}, lineitem_1:{}, lineitem_2:{}}
当我将我的 lineitem 数组更新为
[i1,i2,i3,i4]
this.refs 没有改变,它仍然是
{lineitem_0:{}, lineitem_1:{}, lineitem_2:{}}
为什么 refs 对象在渲染之间不更新? LineItemRow 组件更新正确,所以我知道它在这方面没有问题。任何见解将不胜感激!
____Edit____(要求为上下文添加更多代码)
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>
);
}
})
【问题讨论】:
-
如何以及何时更新 lineitem 列表? this.pros.onChange 中传入了什么样的函数?你有更相关的代码吗?
-
我正在使用通量,因此 lineitem 列表是从 data_store 更新并由父组件传入的。我已经检查过了,这一切正常。传入的 onChange 函数将数据保存到后端,并在 lineitem 更改时更新 store。 onchange 函数调用 getAjaxData()。方法 这是代码中最相关的部分,但我会发布我的其他代码。其他一切都在正常工作。我很确定这是一个反应的事情。因为正在更新的 {lineitems} 组件列表是正确的,甚至具有正确的 refs。
-
我在 facebooks 文档上阅读了更多关于 refs 的信息。我有点不确定是否可以在初始渲染后动态添加更多引用。我在您的代码中看不到任何错误,所以这是我唯一的理论 atm。继续搜索,也许你能找到一些东西here。 (如果您还没有尝试过)
-
是的,我也是这么想的。似乎很奇怪,他们不会在每次渲染后更新 refs。我觉得我不能成为唯一一个试图以这种方式弄乱代码的人。也许我在做一些本质上错误的事情,或者反应创造者不赞成?我找到了这个mattzabriskie.com/blog/react-referencing-dynamic-children,但它似乎不是我需要的,因为我没有使用儿童。
-
从我对文档所说的 refs 的印象来看,应该避免使用它。我看到您正在使用 LineItemRowsWrapper 的参考。我认为您可以将 LineItemsRowsWrapper 中的 ajaxData 传递给从 DocumentContent 发送的 onChange,而无需使用 ref。然后你就可以摆脱那个裁判了。 ref 主要用于在渲染后访问 html 中的数据。您可以使用它来访问孩子,但还有其他可能更多“反应器”的方式来做到这一点。不过(我认为)它并不能解决您的问题。
标签: javascript render reactjs refs