React refs不会在渲染之间更新

时间:2015-03-31 06:07:03

标签: javascript render reactjs refs

所以我有这个组件

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>
    );
  } 
})

2 个答案:

答案 0 :(得分:6)

在&#34;注意&#34;部分下在refs https://facebook.github.io/react/docs/more-about-refs.html

的反应文档中
  

&#34;永远不要访问任何组件的渲染方法中的引用 - 或者同时访问   任何组件的渲染方法甚至可以在调用中的任何位置运行   堆栈&#34;

这正是你正在做的事情。

相反,您应该在this.state中存储有关组件的状态,或者在this.props

中存储组件的属性

答案 1 :(得分:0)

删除所有引用和迭代以读取数据。

应该调用一直传递给LineItem组件的onchange处理程序,并仅传递更改的数据。 (单个LineItem数据)

然后在具有状态处理(DocumentContent)的组件处回来。

创建一个动作ShootActions.updateLineItem(),用于更新商店中的相关订单项,然后发出更改并再次呈现所有内容。