javascript – 在React useEffect钩子中引用过时状态
作者:互联网
我想在卸载组件时将状态保存到localStorage.
这曾经在componentWillUnmount中工作.
我试着用useEffect钩子做同样的事情,但似乎在useEffect的return函数中状态不正确.
这是为什么?如何在不使用课程的情况下保存状态?
这是一个虚拟的例子.按关闭时,结果始终为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"));
解决方法:
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.这比在每次更新时都没有传递任何内容的方法要好.除非您非常频繁地更改计数(每隔几毫秒),否则您不会看到性能问题,只要计数发生变化,就可以写入localStorage.
useEffect(() => { ... }, [count]);
如果你坚持只在unmount上写入localStorage,你可以使用一个丑陋的黑客/解决方案 – 参考.基本上,您将创建一个在组件的整个生命周期中存在的变量,您可以从其中的任何位置引用该变量.但是,您必须手动将状态与该值同步,这非常麻烦. Refs不会给你上面提到的闭包问题,因为refs是一个带有当前字段的对象,多次调用useRef将返回相同的对象.只要你改变.current值,你的useEffect总是(只)读取最新的值.
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,reactjs,react-hooks 来源: https://codeday.me/bug/20191008/1869761.html