React refs不会在渲染之间更新

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)

jef*_*ile 6

关于refs https://facebook.github.io/react/docs/more-about-refs.html的反应文档中的"警告"部分

"永远不要访问任何组件的render方法中的refs - 或者当任何组件的render方法甚至在调用堆栈中的任何地方运行时."

这正是你正在做的.

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


dan*_*haw 0

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

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

然后,通过状态处理 (DocumentContent) 在组件中对此进行处理。

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