现在,反应组件的开发基本上是使用钩子。钩子非常方便,但是如果您不关注,您会在闭合陷阱中遇到一个坑。
我相信许多使用钩子的人遇到了这个坑。今天,我们将探索原因以及如何解决钩子闭合陷阱。
首先,这样的代码,您认为有一个问题:
使用USESTATE创建一个计数状态,定期在一个Userfect中修改它,然后定期在UseeeeFect中打印最新的计数值。
让我们运行:
打印不是我们期望的0、1、2、3,而是0、0、0和0。为什么?
这是So称为的关闭陷阱。
首先,我们回顾钩子的原理:钩子是将记忆的链接列表存储在光纤节点上,每个钩子都会从相应的链接列表元素发送自己的值。
例如,上面的Usestate,使用效果和使用效率的三个钩子对应于链接列表中的3个记忆:
然后,钩子要访问自己的记忆力以完成逻辑。
有两个阶段:挂钩链接列表的创建和更新,即安装和更新。第一次,转到安装座创建链接列表,然后转到更新。
例如,实施使用效率:
请特别注意DEPS参数的处理。
稍后如何处理?
将新引入的DEP与先前现有的记忆端DEP进行比较以进行比较。如果不更改,它将由先前发送的函数直接使用,否则将使用新功能。
DEP比较的逻辑很容易理解。如果以前的DEP为null,则返回错误是不相等的,否则将与数组进行比较:
所以:
如果使用效率的第二个参数被传递到未定义或空的中,则每次都将执行。
如果您传递一个空数组,则只能执行一次。
否则,是否将更改数组中的每个元素以决定是否执行。
我们应该熟悉这些,但是现在我们可以从源代码中明确清楚。
同样,USEMEMO,USECALLBACK等是相同的DEPS处理:
在澄清了诸如使用效果之类的钩子访问数据之后,如何判断是否执行传输函数,然后返回查看关闭陷阱问题。
我们写了这一点:
DEPS被引入空数组中,因此仅执行一次。
相应的源代码实现是:
如果需要执行的效果将用hasffect标记,则稍后将执行:
由于deps数组是一个空数组,因此没有标记的aSeffect,也不会执行。
我们知道为什么只执行一次,执行情况有什么问题?实际上只需要设置一次计时器吗?
计时器实际上只需要设置一次,但是计时器中使用了变化的状态。这是个问题:
DEPS设置空气阵列,然后仅首次执行渲染多次输入该功能:
但是状态正在发生变化,但是函数执行始终引用了初始状态。
如何解决这个问题呢?
每个状态更改以重新创建计时器,并且使用新状态变量还不足:
那是::
这样,每次计数发生变化时,它将执行最新的计数函数:
现在不是全部0,但是这种混乱的印刷是怎么回事?
那是因为现在确实是一个FN来设置一个新的计时器,但是前一个计时器尚不清楚,您需要添加一部分清晰的逻辑:
使用ClearInterval,每次执行新功能时,计时器都会在最后一次设置。
再试一次:
现在,它与我们的期望,打印0、1、2、3和4一致。
许多同学学习了使用效果,但不知道他们想返回清洁功能,现在知道为什么要清除最后一个设置的计时器和事件监视器,然后再执行。
这样,我们完美地解决了钩闭合陷阱的问题。
尽管钩子很方便,但也存在关闭陷阱的问题。
我们已经通过了钩子的实施原则:
将链接列表存储在光纤节点的记忆属性中。链接的列表节点和钩子对应于相应节点上的一个-to -One和每个钩访问数据。
使用效果,USEMOMO,USECALLBACK等都有DEP参数。在实施它时,它将比较两个新的和旧的深度。如果它更改,它将被重新执行。因此,未定义和null将每次执行,[]只能执行一次,并且[状态]将在状态更改后再次执行。
闭合陷阱的原因是使用效果的钩子中的某个状态,但没有将其添加到deps数组中。这会导致状态更改但不执行新传输的功能。先前的状态仍在引用。
闭合陷阱的解决方案也非常简单。正确设置DEPS数组,以便每次使用的状态将执行新功能并引用新状态。但是,请注意清理下一个计时器,事件监视器等。
挂钩闭合陷阱的原因是要了解钩子的原理,何时将执行新引入的功能以及何时不会执行。
钩子的原理确实并不困难,也就是说,在记忆的链接列表上的节点的访问数据以完成其逻辑。唯一需要注意的是由DEPS阵列引起的关闭陷阱。