array.map中onClick函数失效,请求解释bind()用法及解决方法
嘿,我来帮你把这两个问题掰明白——先搞懂bind()到底干啥用,再解决map里onClick失效的问题!
一、为啥要用bind(this)?
在React类组件里,类的方法默认是不会自动绑定组件实例的this的。也就是说,如果你不在constructor里用this.changeState = this.changeState.bind(this),当你在onClick里调用this.changeState时,方法里的this会变成undefined(严格模式下),自然就没法访问this.props或者组件的其他属性了。
bind()的作用就是把方法里的this强行绑定到你指定的对象上——这里就是绑定到TodoList组件的实例,这样当changeState被调用时,里面的this就指向组件本身,你才能正常执行this.props.toggleToDo(param)这类操作。
二、解决array.map中onClick失效的问题
看你代码里的map用了普通的function(listValue),这里有个坑:普通函数会创建自己的this上下文,导致里面的this和组件实例的this不是同一个,所以调用this.changeState时就会出问题。给你几个靠谱的解决办法:
方法1:用箭头函数遍历map
箭头函数不会创建自己的this,会自动继承外层(也就是render方法)的this,这样就能正常访问组件的changeState方法了。而且还能方便地给changeState传参数:
render() { const todolist = this.props.todos; return ( <div> <ul> {todolist.map((listValue, index) => ( <li key={index} // 记得加key,React要求列表项要有唯一key onClick={() => this.changeState(listValue.id)} // 这里可以传参数 > {listValue.text} </li> ))} </ul> </div> ); }
方法2:给map传第二个参数指定this
如果习惯用普通函数,可以给map的第二个参数传入组件的this,这样普通函数里的this就指向组件实例了:
render() { const todolist = this.props.todos; return ( <div> <ul> {todolist.map(function(listValue, index) { return ( <li key={index} onClick={this.changeState} > {listValue.text} </li> ); }, this)} {/* 这里传入this,指定map回调里的this */} </ul> </div> ); }
方法3:用类箭头函数定义changeState(推荐)
如果你用的是支持class fields的环境(现在大部分项目都支持),可以直接把changeState定义成箭头函数,这样就不用在constructor里bind了,箭头函数会自动绑定组件的this:
class TodoList extends Component { // 不用写constructor和bind了 changeState = (todoId) => { console.log('change'); this.props.toggleToDo(todoId); } render() { const todolist = this.props.todos; return ( <div> <ul> {todolist.map((listValue, index) => ( <li key={index} onClick={() => this.changeState(listValue.id)} > {listValue.text} </li> ))} </ul> </div> ); } }
这样处理后,你的onClick点击事件就能正常触发changeState函数啦!
内容的提问来源于stack exchange,提问作者devd_102

