当前位置: 首页 > Web前端 > JavaScript

你觉得Hooks很烦人吗?

时间:2023-03-27 10:20:34 JavaScript

大家好,我是Kason。昨天有朋友给我发了一个demo,我来解释一下原因。看到了,好人,一个小demo,知识点包括:Hooks的闭包问题的状态是如何组装的,相信看完这个demo,你会对函数组件有更深的理解。令人困惑的DemoDemo包含一个按钮和一个列表。Add{list.map(val=>val)}

点击按钮,调用add方法,插入item列表:让i=0;导出默认函数App(){const[list,setList]=useState([]);constadd=()=>{//...};return(Add{list.map(val=>val)}
);}显示效果:烧脑的部分是通过调用add方法插入的是单击,将调用add方法的按钮:constadd=()=>{setList(list.concat({i++}));};点击添加按钮7次最终显示效果:那么问题来了,点击带有数字的按钮后会有什么效果(会调用和点击添加按钮一样的add方法)?状态组装和关闭问题如果您认为将插入一个新按钮:那您就错了。正确答案是:点击对应的按钮后,列表长度变成按钮对应的数字+1,最后一项的数字为点击前的最大数字+1。比如点击前最大数为6,如果点击0,则列表长度变为0+1=1,最后一项为6+1=7:如果点击2,则列表长度变为2+1=3,最后一项是6+1=7:这是两个因素的结果:Hooks的闭包问题和state组装的原因再来看add方法:constadd=()=>{setList(list.concat({i++}));};点击按钮后会调用add,所以会根据add所属的上下文(App函数)形成一个闭包。闭包包括:addlistsetListi属于模块级作用域,不在闭包中。list和setList来自useState调用后的返回值:const[list,setList]=useState([]);一个常见的认知误区是:多次调用useState返回的列表是同一个引用。事实上,每次调用useState返回的list都是根据下面的公式计算出来的:basestate+update1+update2+...=currentstate,所以是一个全新的对象。如果想了解更详细的update和state计算,可以参考React技术揭秘Whenfirstscreenrendered:thefirstrenderoftheAppcomponentcreatesalist=[]Add依赖add形成一个闭包Package,在closure=[]中列出接下来点击Add按钮:调用add方法,该方法来自首屏渲染创建的闭包。add方法中的list来自同一个闭包,所以list=[]{i++}依赖add形成一个闭包,而list中的listclosure=[]因此,对于0号按钮,任何时候点击它,实际上都会执行:setList([].concat({i++}));那么如何解决这个问题也很简单,把setList的参数改成一个函数Form://beforesetList(list.concat({i++}));//setList(list=>list.concat({i++}));函数参数中的列表来自Hooks中保存的列表,而不是闭包中的列表。总结由于Hooks总是在渲染组件时计算新的状态,这给Hooks带来了沉重的精神负担。相比之下,用细粒度更新实现的Hooks(比如VUE的CompositionAPI)可以实时更新状态,操作更直观。在使用Hooks的过程中,你有遇到过类似的头痛问题吗?欢迎加入人类优质前端框架研究组,带头