React函数包裹延迟调用疑问:TodoList删除任务实现困惑
嘿,我来帮你把这个问题掰扯明白——这绝对是React新手最容易踩的坑之一,咱们一步步拆解:
首先搞懂React事件处理的核心要求
React的onClick(以及其他事件属性)需要接收的是一个函数引用,简单说就是:你要告诉React「当用户点击这个元素时,去执行哪个函数」。这个函数会在点击事件触发时才被调用,而不是在组件渲染的时候。
你的写法为什么不对?
看你写的代码:
<button onClick={this.deleteTask(i)}>Delete</button>
这里的this.deleteTask(i)是直接执行了这个函数——注意,是在组件渲染、生成这段JSX的瞬间就执行了,而不是等点击按钮的时候!
那这个执行的结果是什么呢?你的deleteTask函数内部调用了setState,而setState的返回值是undefined。所以相当于你给onClick传了个undefined,点击按钮自然没反应;更糟的是,每次组件渲染(比如删除任务后state变化重新渲染),这个函数都会被执行一遍,导致任务被意外删除,完全不符合你的预期。
讲师说的「这是函数的执行结果」,指的就是你把deleteTask(i)运行后得到的undefined传给了onClick,而不是把函数本身(或者一个能触发它的函数)传过去。
推荐写法为什么能work?
再看正确的写法:
<button onClick={() => this.deleteTask(i)}>Delete</button>
这里你传递给onClick的是一个新的无参箭头函数的引用。组件渲染时,这个箭头函数并没有被执行,只是把它的「地址」交给了onClick。只有当用户点击按钮的时候,React才会调用这个箭头函数,然后在箭头函数内部再去执行this.deleteTask(i)——这才是你想要的「点击时删除任务」的时机!
打个生活化的比方:你的写法相当于你刚跟朋友说「帮我拿个杯子」,朋友立刻就去拿了;而推荐写法是跟朋友说「等我喊‘拿’的时候,你再帮我拿杯子」,只有你发出指令(点击),动作才会触发。
补充:还有其他写法吗?
除了箭头函数,你也可以用bind来绑定参数,效果是一样的:
<button onClick={this.deleteTask.bind(this, i)}>Delete</button>
bind会返回一个新的函数,这个函数已经提前绑定了this和i参数,同样是在点击时才会执行deleteTask。不过箭头函数的写法更直观易懂,现在也是React社区更常用的方式。
内容的提问来源于stack exchange,提问作者turtlefish12

