useState 在 useEffect 中定义后保持初始状态

Posted

技术标签:

【中文标题】useState 在 useEffect 中定义后保持初始状态【英文标题】:useState keeps initial state after defining it in useEffect 【发布时间】:2022-01-19 11:24:59 【问题描述】:

我有一个从 API 获取一些数据的异步函数。因为我需要这些数据来正确加载我的组件,所以我决定在 useEffect 中获取数据,然后将其存储在 useState 中,这样就可以了。但是,如果我尝试通过控制台记录它,它只会显示其初始状态,这在技术上意味着它仍未设置或控制台日志在分配 useState 之前运行。

提前感谢您的帮助。

const [categories, setCategories] = useState([])

useEffect(() => 
    fetchListProductCats().then(function(result)
        setCategories(result.data)
    )
    console.log(categories) // returns -> []
    
, []);

if(!categories.length)
    return "loading"

【问题讨论】:

你自己说的,它是异步的,你记录的时候数据还没有设置。 是的,我就是这么想的,但是我要如何等待异步函数完成呢? 好吧,在这种情况下,不仅你的函数是异步的,而且在 React 中设置状态也是异步的。因此,您将需要使用另一种效果来等待对categories 的更改(如几个答案中所述) 【参考方案1】:

async 使用 Promise 函数,确保你知道它的含义。

此代码中的 console.log 行始终在 Promise 解决之前运行。

如果你想观察类别的变化,使用另一个useEffect

useEffect(() => 
  console.log(categories);
, [categories]);

【讨论】:

感谢您的回答,但如果我按照您的建议执行操作,console.log 会运行两次,第一次运行时会像以前一样记录一个空数组,第二次会记录填充后的数组大批。我不确定,因为我对 React 还很陌生。在性能方面不是很差吗?我的意思是,如果它是一个功能,它可能不会产生明显的效果,但是如果我的项目规模更大,它肯定会导致延迟? @Luke_KS 有一个official document 解释了这一点。实际上第二个参数决定了这个钩子的运行性能。通常,每次重新渲染时,只会对数组中的值进行几次比较。它是安全的,并且比重新渲染时其他步骤消耗的性能要低得多。【参考方案2】:

您的状态已经使用您希望其显示类别及其初始值的数据进行了更新,因为您已经渲染了 useEffect 没有依赖关系。 并且在更新之前得到了安慰。 尝试使用以下代码 sn-ps 记录。

useEffect(() => 
    console.log(categories)
, [categories]);

【讨论】:

【参考方案3】:

React setState 是异步的。调用函数后不会立即更新。它将首先通过重新渲染过程来更新用户界面。重新渲染完成后,useEffect 挂钩中提供的函数将被调用。

useEffect(()=>
  console.log(categories)
, [categories]) 

【讨论】:

以上是关于useState 在 useEffect 中定义后保持初始状态的主要内容,如果未能解决你的问题,请参考以下文章

React useState 和 useEffect 混淆

useMemo 与 useEffect + useState

无法获取更新后的状态值 useState 和 UseEffect

在 useEffect 中使用 useState 值而不使状态更新 useEffect

为啥 useState 钩子在 useEffect() 中使用循环时不更新

useState 中的变量未在 useEffect 回调中更新