React代码报错:TypeError: Cannot read property 'remove' of undefined 求助
解决React中
TypeError: Cannot read property 'remove' of undefined的问题 我来帮你排查并解决这个问题,先拆解代码里的几个关键问题:
问题1:map回调函数中的this指向错误
在List组件的render方法里,你用普通函数作为map的回调:
this.state.arrayNote.map(function(note, i){ return (<Note index={i} handleRemove={this.remove} key={i}>{note}</Note>) })
普通函数的this在这个场景下不会指向组件实例,导致this.remove是undefined——当点击Delete按钮触发handleRemove时,自然就抛出了你看到的错误。
解决办法:
改用箭头函数,它会自动继承外部的this指向:
this.state.arrayNote.map((note, i) => { return (<Note index={i} handleRemove={this.remove} key={i}>{note}</Note>) })
问题2:直接修改state的错误操作
在remove方法里,你直接修改了this.state的数组:
this.state.arrayNote.splice(index, 1); this.setState(this.state);
React明确禁止直接修改state,因为这会跳过React的状态更新机制,可能导致组件不渲染或出现不可预测的行为。
解决办法:
创建原数组的副本,修改副本后再用setState更新:
remove(index){ const newArray = [...this.state.arrayNote]; // 用扩展运算符创建数组副本 newArray.splice(index, 1); this.setState({ arrayNote: newArray }); // 更新状态 }
问题3:bind方法放在render里的性能浪费
你在render方法里写了this.remove = this.remove.bind(this),这会导致每次组件渲染时都重新绑定一次函数——虽然不会直接报错,但会带来不必要的性能消耗。
解决办法:
把bind移到constructor里,只绑定一次:
constructor(props){ super(props); this.state = { arrayNote: ['ha', 'hi', 'hu'] }; this.remove = this.remove.bind(this); // 移到此处,仅初始化时绑定一次 }
然后删除render里的this.remove = this.remove.bind(this)语句。
修正后的完整代码
class Note extends React.Component{ constructor(props){ super(props); } xoa(){ var {index, handleRemove} = this.props; handleRemove(index); } render(){ return( <div> <p>{this.props.children}</p> <button onClick={this.xoa.bind(this)}> Delete </button> </div> ); } } class List extends React.Component{ constructor(props){ super(props); this.state = { arrayNote: ['ha', 'hi', 'hu'] }; this.remove = this.remove.bind(this); } remove(index){ const newArray = [...this.state.arrayNote]; newArray.splice(index, 1); this.setState({ arrayNote: newArray }); } render(){ return( <div>{this.state.arrayNote.map((note, i) => { return (<Note index={i} handleRemove={this.remove} key={i}>{note}</Note>) })} </div> ); } } ReactDOM.render( <List />, document.getElementById("root") );
<div id="root"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.11.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script>
现在运行修正后的代码,点击Delete按钮就能正常删除对应的笔记,控制台也不会再报错了。
内容的提问来源于stack exchange,提问作者Nhat Nguyen
相关产品推荐
相关产品推荐

