gpt4 book ai didi

javascript - 在 React useEffect Hook 中引用过时的状态

转载 作者:可可西里 更新时间:2023-11-01 02:36:45 26 4
gpt4 key购买 nike

我想在卸载组件时将状态保存到 localStorage。这曾经在 componentWillUnmount 中工作。

我尝试用 useEffect 钩子(Hook)做同样的事情,但在 useEffect 的返回函数中似乎状态不正确。

这是为什么呢?如何在不使用类的情况下保存状态?

这是一个虚拟的例子。当您按下关闭时,结果始终为 0。

import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";

function Example() {
const [tab, setTab] = useState(0);
return (
<div>
{tab === 0 && <Content onClose={() => setTab(1)} />}
{tab === 1 && <div>Why is count in console always 0 ?</div>}
</div>
);
}

function Content(props) {
const [count, setCount] = useState(0);

useEffect(() => {
// TODO: Load state from localStorage on mount

return () => {
console.log("count:", count);
};
}, []);

return (
<div>
<p>Day: {count}</p>
<button onClick={() => setCount(count - 1)}>-1</button>
<button onClick={() => setCount(count + 1)}>+1</button>
<button onClick={() => props.onClose()}>close</button>
</div>
);
}

ReactDOM.render(<Example />, document.querySelector("#app"));

CodeSandbox

最佳答案

I tried to do the same with the useEffect hook, but it seems state is not correct in the return function of useEffect.

这是由于关闭造成的。闭包是函数对其范围内变量的引用。您的 useEffect 回调仅在组件安装时运行一次,因此返回回调引用初始计数值 0。

这里给出的答案是我推荐的。我会推荐@Jed Richard 将 [count] 传递给 useEffect 的答案,它具有仅在 count 更改时写入 localStorage 的效果。这比在每次更新时完全不传递任何内容的方法要好。除非您非常频繁地更改计数(每隔几毫秒),否则您不会看到性能问题,并且只要 count 发生变化,就可以写入 localStorage

useEffect(() => { ... }, [count]);

如果您坚持只在卸载时写入 localStorage,您可以使用一个丑陋的 hack/解决方案 - refs。基本上,您将创建一个变量,该变量在组件的整个生命周期中都存在,您可以从其中的任何地方引用它。但是,您必须手动将您的状态与该值同步,这非常麻烦。 Refs 不会给你上面提到的闭包问题,因为 refs 是一个带有 current 字段的对象,多次调用 useRef 将返回同一个对象。只要您改变 .current 值,您的 useEffect 就可以始终(仅)读取最新的值。

CodeSandbox link

const {useState, useEffect, useRef} = React;

function Example() {
const [tab, setTab] = useState(0);
return (
<div>
{tab === 0 && <Content onClose={() => setTab(1)} />}
{tab === 1 && <div>Count in console is not always 0</div>}
</div>
);
}

function Content(props) {
const value = useRef(0);
const [count, setCount] = useState(value.current);

useEffect(() => {
return () => {
console.log('count:', value.current);
};
}, []);

return (
<div>
<p>Day: {count}</p>
<button
onClick={() => {
value.current -= 1;
setCount(value.current);
}}
>
-1
</button>
<button
onClick={() => {
value.current += 1;
setCount(value.current);
}}
>
+1
</button>
<button onClick={() => props.onClose()}>close</button>
</div>
);
}

ReactDOM.render(<Example />, document.querySelector('#app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>

<div id="app"></div>

关于javascript - 在 React useEffect Hook 中引用过时的状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53633698/

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