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

新React文档:不要滥用效果

时间:2023-03-28 13:34:06 HTML

大家好,我是Kason。你或者你的同事在使用useEffect的时候有没有遇到过下面的场景:当状态a发生变化之后你想发起一个请求,所以你使用了useEffect:useEffect(()=>{fetch(xxx);},[a])这段代码运行正常,上线后没有问题。随着需求不断迭代,其他地方也会修改状态a。但是在该需求中,statea发生变化后不需要发起请求。不想动之前的代码,又要修复这个bug,所以加了一个判断条件:useEffect(()=>{if(xxxx){fetch(xxx);}},[a])有一天,需求又变起来了!现在请求还需要b字段。很简单,你只是把b添加为useEffect的依赖:useEffect(()=>{if(xxxx){fetch(xxx);}},[a,b])随着时间的推移,你逐渐发现是否发送请求与if条件有关。是否发送请求还与a、b等依赖有关。A、B等依赖关系,涉及到很多需求。无法确定何时发送请求。上面的场景似曾相识,新的React文档已经明确提供了解决方案。欢迎加入人类优质前端框架群,带点理论知识飞上天。新文档中的这一部分称为与效果同步,目前处于草案状态。但是其中提到的一些概念对于所有React开发者来说应该都很清楚。首先,效果部分是EscapeHatches章节的一部分。从命名可以看出,开发者不一定需要使用效果,这只是特殊情况下的逃生通道。React中有两个重要的概念:渲染代码(renderingcode)事件处理器(eventhandler)渲染代码是指开发者编写的组件渲染逻辑,最终会返回一段JSX。例如,渲染代码在以下组件中:functionApp(){const[name,update]=useState('KaSong');return

Hello{name}
;}Rendering代码的特点是:它应该是一个没有副作用的纯函数。以下渲染代码包含副作用(计数变化),不推荐:letcount=0;functionApp(){count++;const[name,update]=useState('卡松');return
Hello{name}
;}处理副作用事件处理程序是包含在组件中的函数,用于执行用户操作,并且可以包含副作用。以下操作属于Eventhandlers:更新input输入框,提交表单,导航到其他页面。在下面的例子中,组件内部的changeName方法属于Eventhandlers:functionApp(){const[name,update]=useState('KaSong');constchangeName=()=>{update('KaKaSong');}returnHello{name}
;}但是,并非所有副作用都可以在事件处理程序中解决。例如,在聊天室中,发送消息是由用户触发的,应该由事件处理程序处理。另外,聊天室需要随时与服务器保持长连接。保持长连接的行为是一种副作用,但它不是由用户行为触发的。对于这种:视图渲染后触发的sideeffect属于effect,应该由useEffect来处理。回到一开始的例子:statea发生变化后要发起请求,首先要明确你的需求是:statea发生变化,然后需要发起请求或者用户行为需要发起请求,请求依赖状态a作为参数?如果是后者,这是用户行为触发的副作用,那么相关逻辑应该放在Eventhandlers中。假设之前的代码逻辑是:点击按钮,触发stateachangeuseEffect执行,那么发送请求应该改为:点击按钮,在事件回调中获取statea的值,在eventcallback此次修改后,状态a的变化与发送请求之间不再存在因果关系,后续对状态a的修改将不再有无意中触发请求的顾虑。总结当我们写组件的时候,我们应该尽量把组件写成纯函数。对于组件中的sideeffect,首先要明确:是用户行为触发还是view渲染后主动触发?对于前者,将逻辑放在事件处理程序中。对于后者,用useEffect来处理。这就是为什么useEffect所在的章节在新文档中被称为EscapeHatches——在大多数情况下,你不会使用useEffect,它只是在其他情况不适用时的一个escapehatches。