ReactJS V16如何将父函数传递给孙子事件处理程序

时间:2018-04-16 15:48:03

标签: javascript reactjs

我是ReactJS的新手,也是JavaScript的新手,并且已经学习了一些在线教程来学习ReactJS。我正在阅读来自不同版本的教程和信息的混合物,所以我确信我要么完全不理解某个主题,要么在这里混合。

我的顶级对象应用中有一个 updateActiveFlag 功能,我将其作为道具传递给 ItemGroup ,然后选中复选框时我想调用的项目。最终当我理解我做错了什么时,我也会以同样的方式修改状态的其他方面。

当我选中复选框时,我进入控制台:

未定义
未定义
4 //假设我选择了第5个复选框,此方面正常工作

有人可以帮助解释我所犯的错误。似乎当我回到顶级处理程序时,这个'这个'已经迷路了。这时我对使用某些库解决这个问题不感兴趣,除非这是唯一的方法。我希望它可以在这个例子中解决,这样我就可以先更好地理解低级方面,然后我可以考虑一个更合适的方法,如果存在。

修改

现在正在运作

对这篇文章的一些回应突出了我在我的例子中所做的拼写错误。我将代码复制并粘贴到一个更大的原型中,并将ItemGroup和Item中的签名混合在一起,以便反映在示例代码中。

我还根据此线程中的反馈更改了我在App控件中再次传递事件处理程序的方式,现在它正在我需要的时候工作。

最后,引用的重复主题有更多信息可以帮助我更好地理解这一点。 在这种情况下,我不确定如何归功于答案。

const Item = (props) => {
return (
      <li className="row">
         <input className="col-sm-1" type="checkbox" checked={props.item.Active} onChange={() => props.activeFlagHandler(props.index)} />
         <div className="col-sm-2">{props.index}</div>
         <div className="col-sm-3">{props.item.Name}</div>
         <div className="col-sm-3">{props.item.Desc}</div>
         <div className="col-sm-3">{props.item.Amount}</div>
      </li>
   );
};


const ItemGroup = (props) => {
   return (
      <div className="container">
         <h4>{props.name}</h4>
      <ul>
            {props.items.map((item, index) => <Item item={item} index={index} activeFlagHandler={props.activeFlagHandler}/>)}
      </ul>
      </div>
   );
};


class App extends React.Component {

   constructor(props) {
      super(props);
      this.state = {
         Name: "",

         "Accounts": [],
         "Expenses": []
      };
   };


   loadModel( model ) {
      $.getJSON( 'api/UnitTest' ).then();

      // Using arrow function otherwise would get an error saying setState is not a valid function
      // because of binding. Arrow function passes ensures correct execution context is passed along
      $.getJSON( '/Model/0123456789' ).then( (results) => { this.processModel( results ) } );
   };


   processModel( results ) {
      console.log( results );

      this.setState( results );
   };


   updateActiveFlag( index ) {
         //const newState = Object.assign( {}, this.state );
         console.log( this.state );
         console.log( this.prevState );

         console.log( index );
   };


   componentDidMount() {
      this.loadModel( '0123456789' );
   }


   render() {
      return (
         <div>
            <h2>Hello World  {this.state.Name} </h2>
            <ItemGroup name="Expenses" items={this.state.Expenses} activeFlagHandler={(index)=>{this.updateActiveFlag(index)} />
         </div>
      );
   }
}

ReactDOM.render(<App />, document.getElementById("app"));

感谢您的帮助 强文

1 个答案:

答案 0 :(得分:1)

您对this变更的假设是正确的。在JavaScript中this取决于调用函数的位置(所谓的执行上下文)。克服这个问题的方法很少,就像使用这样的bind方法

 constructor(){
   //...
   this.updateActiveFlag = this.updateActiveFlag.bind(this)
 }

无论调用函数的位置(人为地更改为声明上下文),this都将保持不变(App)。传递绑定方法时使用直接形式。

 activeFlagHandler={props.activeFlagHandler}

传递函数本身而不是

的箭头函数形式
 activeFlagHandler={() => props.activeFlagHandler(props.index)}  

通过新的匿名功能。
您的代码中的另一个问题是您实际传递给Item的是一个匿名函数,它不接收任何参数(() => ...)但在Item内部您尝试将参数传递给它onChange={props.activeFlagHandler(props.index)}这是不必要的 在我看来,你有一个正确的想法,一次只关注一个库,我强烈推荐一个很好的资源,official docs具体thinking in react非常有启发性。