本文介绍了在 React useEffect 钩子中引用过时的状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我想在卸载组件时将状态保存到 localStorage
.这曾经在 componentWillUnmount
中工作.
我尝试对 useEffect
钩子做同样的事情,但在 useEffect
的返回函数中似乎状态不正确.
这是为什么?如何在不使用类的情况下保存状态?
这是一个虚拟示例.当您按下关闭时,结果始终为 0.
import React, { useState, useEffect } from "react";从react-dom"导入 ReactDOM;函数示例(){const [tab, setTab] = useState(0);返回 (<div>{tab === 0 &&<Content onClose={() =>setTab(1)}/>}{tab === 1 &&<div>为什么控制台中的计数总是 0?</div>}
);}功能内容(道具){const [count, setCount] = useState(0);useEffect(() => {//TODO: 从 localStorage 加载状态挂载返回 () =>{console.log("count:", count);};}, []);返回 (<div><p>天:{count}</p><button onClick={() =>setCount(count - 1)}>-1</button><button onClick={() =>setCount(count + 1)}>+1<button onClick={() =>props.onClose()}>close</button>
);}ReactDOM.render(, document.querySelector("#app"));
CodeSandbox
解决方案
这是由于关闭造成的.闭包是函数对其作用域内变量的引用.您的 useEffect
回调仅在组件安装时运行一次,因此返回回调引用的初始计数值为 0.
这里给出的答案是我推荐的.我会推荐@Jed Richard 将 [count]
传递给 useEffect
的答案,这具有仅在计数更改时写入 localStorage
的效果.这比在每次更新时完全不传递任何内容的方法要好.除非您非常频繁地(每隔几毫秒)更改计数,否则您不会看到性能问题,只要 count
更改,就可以写入 localStorage
.
useEffect(() => { ... }, [count]);
如果您坚持只在卸载时写入 localStorage
,那么您可以使用一个丑陋的 hack/解决方案 - refs.基本上,您将创建一个在组件的整个生命周期中都存在的变量,您可以从其中的任何位置引用该变量.但是,您必须手动将状态与该值同步,这非常麻烦.Refs 不会给你上面提到的关闭问题,因为 refs 是一个带有 current
字段的对象,多次调用 useRef
将返回同一个对象.只要您改变 .current
值,您的 useEffect
就可以始终(仅)读取最新的值.
CodeSandbox 链接
const {useState, useEffect, useRef} = React;函数示例(){const [tab, setTab] = useState(0);返回 (<div>{tab === 0 &&<Content onClose={() =>setTab(1)}/>}{tab === 1 &&<div>控制台中的计数并不总是 0</div>}
);}功能内容(道具){常量值 = useRef(0);const [count, setCount] = useState(value.current);useEffect(() => {返回 () =>{console.log('count:', value.current);};}, []);返回 (<div><p>天:{count}</p><按钮onClick={() =>{value.current -= 1;setCount(value.current);}}>-1按钮><按钮onClick={() =>{value.current += 1;setCount(value.current);}}>+1按钮><button onClick={() =>props.onClose()}>close</button>
);}ReactDOM.render(, document.querySelector('#app'));
<script src="https://unpkg.com/[email protected]/umd/react.development.js"></script><script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script><div id="app"></div>