gpt4 book ai didi

reactjs - 令人困惑的 React useEffect 钩子(Hook)行为

转载 作者:行者123 更新时间:2023-12-04 14:05:06 24 4
gpt4 key购买 nike

我是 React 的新手,只是在学习了钩子(Hook)类(class)后练习了 useEffect 钩子(Hook)。
我有一个按钮来切换箭头状态的状态变化。

export default function Test() {
const [arrowState, setArrowState] = useState(true);
const [arrowChange, setArrowChange] = useState(false);


const toggleButton = () => {
return setArrowState((arrowState) => {
return !arrowState;
});
};

return (
<>
<div>
<button
type="button"
onClick={toggleButton}
>
Toggle Arrow
</button>
</div>
{arrowChange && <Notific />}
</>
);
}

然后我有一个 useEffect 钩子(Hook),它改变了 arrowChange 的状态。
也有一个超时将 arrowChange 的状态更改为 false - 从而在 2 秒后自动消失按钮。
useEffect(() => {
console.log("first line of useEffect.arrowChange is ", arrowChange);
setArrowChange(true);
console.log(
"immediately after setArrowChange to true. arrowChange is ",
arrowChange
);

setTimeout(() => {
console.log("first line of setTimeOut. arrowChange is ", arrowChange);
arrowChange && setArrowChange(false);
}, 1000);

return () => {
console.log("cleaning up arrowchange. arrowChange is ", arrowChange);
setArrowChange(false);
};
}, [arrowState]);
基于它,我正在显示另一个带有消息的按钮。
function Notific() {
return (
<button
type="button"
onClick={() => setArrowChange(false)}
>
Arrow state has been changed
</button>
);
}
如您所见,我正在记录一些消息以查看效果。我很惊讶地看到,即使在 useEffect 钩子(Hook)开始时将 arrowChange 设置为 true 之后,它在替代事件中仍然显示为 false。
检查这些控制台日志:
cleaning up arrowchange. arrowChange is  false
Test.js:57 first line of useEffect.arrowChange is true
Test.js:59 immediately after setArrowChange to true. arrowChange is true
Test.js:65 first line of setTimeOut. arrowChange is true

Test.js:70 cleaning up arrowchange. arrowChange is true
Test.js:57 first line of useEffect.arrowChange is false
Test.js:59 immediately after setArrowChange to true. arrowChange is false
Test.js:65 first line of setTimeOut. arrowChange is false

Test.js:70 cleaning up arrowchange. arrowChange is false
Test.js:57 first line of useEffect.arrowChange is true
Test.js:59 immediately after setArrowChange to true. arrowChange is true
Test.js:65 first line of setTimeOut. arrowChange is true

Test.js:70 cleaning up arrowchange. arrowChange is true
Test.js:57 first line of useEffect.arrowChange is false
Test.js:59 immediately after setArrowChange to true. arrowChange is false
Test.js:65 first line of setTimeOut. arrowChange is false

Test.js:70 cleaning up arrowchange. arrowChange is false
Test.js:57 first line of useEffect.arrowChange is true
Test.js:59 immediately after setArrowChange to true. arrowChange is true
Test.js:65 first line of setTimeOut. arrowChange is true

最佳答案

要理解代码的输出,您需要了解 react 如何更新状态的基本概念以及 closure 的概念。 .
状态更新是异步的
每次调用状态设置函数,例如 setArrowChange已安排 - 状态不会立即更新。
结果,记录了 arrowChange 的值拨打电话后立即setArrowChange将记录 arrowChange 的旧值.
状态在组件的特定渲染中是恒定的
状态是恒定的;这意味着无论您调用 state setter 函数多少次,组件在重新渲染之前都看不到更新的状态。
setTimeout 的回调函数对状态有闭包
当你创建一个函数是 javascript 时,它会形成一个 closure在其周围范围内。
在您的情况下,setTimeout 的回调函数将记录 arrowChange 的值创建回调函数时生效。
如果在 setTimeout 的时候调用,arrowChangefalse ,并且在计时器到期之前,您将状态更新为 true , 回调函数仍会记录 false因为closure .
useEffect 钩子(Hook)的清理函数对状态有一个闭包cleanup函数也有closurearrowChange ;它记录了 arrowChange 的值这在创建清理函数并从 useEffect 的回调函数返回时生效。钩。
现在我们来看看第一组console.log输出。
第一组:

cleaning up arrowchange. arrowChange is false 
Test.js:57 first line of useEffect.arrowChange is true
Test.js:59 immediately after setArrowChange to true. arrowChange is true
Test.js:65 first line of setTimeOut. arrowChange is true

第一行输出
cleaning up arrowchange. arrowChange is  false
来自 useEffect 的清理功能执行的钩子(Hook):
  • 运行前useEffect再次
  • 组件卸载前

  • 如上所述,它记录了 arrowChange 的值当 useEffect 的清理功能关闭时它关闭了被创建。清理函数的输出表明:
  • arrowChange的值(value)是 false当清理函数被创建并从 useEffect 返回时hook 的回调函数
  • arrowChange的初始值是 false ,所以这个输出如果来自最有可能在 useEffect 时创建的清理函数在组件的初始渲染之后第一次执行钩子(Hook)

  • 接下来的三行
    Test.js:57 first line of useEffect.arrowChange is  true
    Test.js:59 immediately after setArrowChange to true. arrowChange is true
    Test.js:65 first line of setTimeOut. arrowChange is true
    记录 arrowChange 的最新值这很可能是因为 setArrowChange(true)useEffect 的第二行中调用在组件的初始渲染之后执行的钩子(Hook)。
    如果观察 console.log的其他组的输出输出,您会注意到 arrowChange 的值清除函数记录的值与 console.log 记录的值相反。 useEffect 的回调函数中的语句钩。
    这样做的原因是清理函数来自于之前执行的 useEffect钩子(Hook)并记录 arrowChange 的值这在之前执行 useEffect 期间生效钩。 console.log useEffect 的回调函数中的语句钩子(Hook)日志最新值 arrowChange并在 useEffect 的下一次执行中钩子(Hook),这个最新值将成为前一个值,与这个最新值相反的将成为最新值。

    关于reactjs - 令人困惑的 React useEffect 钩子(Hook)行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68836817/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com