How to create a stale closure like the one in React#39;s useEffect hook without using the actual useEffect hook?(如何在不使用实际的useEffect钩子的情况下创建像React的useEffect钩子中那样的陈旧闭包?)
问题描述
我知道闭包是如何工作的,但是我不能理解在没有详尽的依赖数组的情况下,陈旧的闭包 我做错了什么?当我们没有提供完整的依赖数组时,我应该怎么做才能创建像我们在Reaction的 当我们没有在useEffect中给出详尽的依赖关系时,为什么会创建陈旧的闭包?为什么 为完整起见,下面是使用React的useEffect的代码片段,其中我们没有为Reaction的useEffect提供详尽的依赖项数组,因此创建了一个陈旧的闭包:
我做错了什么?我应该怎么做才能创建一个陈旧的闭包,比如
我们在Reaction的Use Effect中得到的那个,当我们没有提供完整的
依赖项数组? 您不会得到陈旧的闭包,因为您只调用了 为了重新呈现功能性Reaction组件,Reaction再次调用组件函数。这将创建一个新作用域,该作用域与上次调用函数组件时创建的作用域没有链接。 若要获取过时的关闭,您需要多次调用useEffect
是如何在Reaction的useEffect
中创建的。为此,我试图复制一个陈旧的闭包,就像在Reaction的useEffect
中一样,不使用useEffect
,但是我无法创建它。我的代码不会创建陈旧的闭包,而是在每个时间间隔记录一个正确值。请您看一下下面的片段,然后告诉我:
useEffect
中得到的那样的陈旧闭包?(参考代码在文章的末尾)
useEffect
钩子回调中的代码不像普通函数那样使用词法作用域,并打印实际值?
function createIncrement(incBy) {
let value = 0;
function increment() {
value += incBy;
console.log(value);
}
function useEffect(fun) {
fun()
}
useEffect(function() {
setInterval(function log() {
// what should I do to create a stale closure here?
// So that if I change the value it should show me the old value
// as it does when using React's useEffect without exhaustive dependencies array
console.log(`Count is: ${value}`); // prints correct value each time
}, 2000);
});
setTimeout(() => {
increment(); // increments to 5
increment(); // increments to 6
}, 5000);
return [increment];
}
const [increment] = createIncrement(1);
increment(); // increments to 1
increment(); // increments to 2
increment(); // increments to 3
increment(); // increments to 4
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
function WatchCount() {
const [count, setCount] = useState(0);
useEffect(function () {
setInterval(function log() {
// No matter how many times you increase the counter
// by pressing the button below,
// this will always log count as 0
console.log(`Count is: ${count}`);
}, 2000);
}, []);
return (
<div>
{count}
<button onClick={() => setCount(count + 1)}>Increase</button>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<WatchCount />, rootElement);
推荐答案
createIncrement
函数一次。createIncrement
。function createIncrement(incBy, functionCallIdentifier, intervalDelay) {
let value = 0;
function increment() {
value += incBy;
console.log("inside call: " + functionCallIdentifier + " - value: " + value);
}
increment();
function useEffect(fun) {
fun();
}
useEffect(function () {
setInterval(function log() {
console.log("inside call: " + functionCallIdentifier + " - count: " + value);
}, intervalDelay);
});
}
createIncrement(1, "first call", 2000);
// calling again but 'setInterval' set in the first call will continue
// to log the latest value of variable "value" that it closed over, i.e. 1
createIncrement(2, "second call", 4000);
为什么要创建过时的闭包,而我们没有给出详尽的 使用中的依赖项是否有效?为什么useEffect中的代码不影响 钩子的回调只需使用词法作用域,就像普通函数一样 是否打印实际值?上面的代码示例应该会让您了解创建陈旧闭包的原因。
useEffect
的回调函数确实使用了词法作用域,但不同之处在于再次调用函数组件会创建一个新作用域,但是组件的上一次呈现中设置的useEffect
钩子的旧回调函数将继续看到创建它的作用域中的值。
此行为不特定于反应-这是javascript中每个函数的行为方式:每个函数在其创建范围内关闭。
在useEffect
挂接中设置新回调之前,在清除前一个回调之前,旧回调将继续记录它关闭的作用域中的值。
下面的代码示例使用清理函数清除第一次调用createIncrement
函数时设置的间隔。
function createIncrement(incBy, functionCallIdentifier, useEffectCleanupFn) {
if (useEffectCleanupFn) {
useEffectCleanupFn();
}
let value = 0;
function increment() {
value += incBy;
console.log("inside call: " + functionCallIdentifier + " - value: " + value);
}
increment();
let cleanupFn;
function useEffect(fun) {
cleanupFn = fun();
}
useEffect(function () {
let id = setInterval(function log() {
console.log("inside call: " + functionCallIdentifier + " - count: " + value);
}, 2000);
return () => clearInterval(id);
});
return cleanupFn;
}
let cleanupFn1 = createIncrement(1, "first call");
setTimeout(() => {
createIncrement(2, "second call", cleanupFn1);
}, 4000);
这篇关于如何在不使用实际的useEffect钩子的情况下创建像React的useEffect钩子中那样的陈旧闭包?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何在不使用实际的useEffect钩子的情况下创建像React的useEffect钩子中那样的陈旧闭包?
基础教程推荐
- 动态更新多个选择框 2022-01-01
- Karma-Jasmine:如何正确监视 Modal? 2022-01-01
- 角度Apollo设置WatchQuery结果为可用变量 2022-01-01
- 当用户滚动离开时如何暂停 youtube 嵌入 2022-01-01
- 响应更改 div 大小保持纵横比 2022-01-01
- 在for循环中使用setTimeout 2022-01-01
- 在 JS 中获取客户端时区(不是 GMT 偏移量) 2022-01-01
- 我什么时候应该在导入时使用方括号 2022-01-01
- 有没有办法使用OpenLayers更改OpenStreetMap中某些要素 2022-09-06
- 悬停时滑动输入并停留几秒钟 2022-01-01