如何立即更新 react useState?

Posted

技术标签:

【中文标题】如何立即更新 react useState?【英文标题】:How to update react useState without delay? 【发布时间】:2020-10-16 13:17:37 【问题描述】:

当我调用fetchProducts 时,我希望在运行下一行代码之前更新 productPage 状态,因为下一行需要更新后的状态。

状态仅在函数完成运行后更新。无论我将console.log(productPage) 放在fetchProducts 函数中的哪个位置,它都会返回调用函数之前的状态。

   const [productPage, setProductPage] = useState(1)
   const [displayProducts, setDisplayProducts] = useState([])

   const fetchProducts = async () => 

      setProductPage(productPage + 1) // DOES NOT UPDATE UNTIL AFTER FUNCTION RUNS

      const newProductsData = await fetch(`/api/getproducts?page=$productPage`)
      const newProductsArr = await newProductsData.json()
      setDisplayProducts(displayProducts.concat(newProductsArr))

   

这可能吗?我找到了解决该问题的方法,但感觉很笨拙且不理想。

我也在使用 next.js,我不确定这是否会有所作为。我不能使用普通变量,因为它们在每次渲染时都会重置。

【问题讨论】:

将 productPage + 1 存储在函数顶部的 const 中,然后只使用该 var 吗?在功能范围内做你想执行的任务,完成后设置状态。 【参考方案1】:

setProductPage 将更新状态并触发新的渲染。 productPage 不是状态,它只是一个变量,保存您使用 useState 时的状态值。它永远不会改变,它将始终具有相同的价值。你认为它改变了,但实际上,函数只是再次执行,但现在 productPage 分配了新值。

那你能做什么?你有两个选择。

它使用useEffect,它将查看productPage是否发生变化(每次执行函数=重新渲染),如果是,它将获取数据并使用setDisplayProducts重新渲染在displayProducts 中具有新值的组件。如果您计划使用其他方式更新 productPage 并且希望它们也触发 fetch,这很好。

const [productPage, setProductPage] = useState(1)
const [displayProducts, setDisplayProducts] = useState([])

const fetchProducts = async () => 
   setProductPage(productPage + 1);


useEffect(() => 
    const getDisplayProducts = async () => 
        const newProductsData = await fetch(`/api/getproducts?page=$productPage`)
        const newProductsArr = await newProductsData.json()
        setDisplayProducts(displayProducts.concat(newProductsArr))
    ;

    getDisplayProducts();
, [productPage]);

第二个是将新值存储在变量中,将变量传递给setProductPage,但在提取中使用变量而不是productPage

const [productPage, setProductPage] = useState(1)
const [displayProducts, setDisplayProducts] = useState([])

const fetchProducts = async () => 
    const nextProductPage = productPage + 1;

    setProductPage(nextProductPage);
    const newProductsData = await fetch(`/api/getproducts?page=$nextProductPage`)
    const newProductsArr = await newProductsData.json()
    setDisplayProducts(displayProducts.concat(newProductsArr));
;

【讨论】:

感谢您详细解释 useState 挂钩的工作原理。 useEffect hook 是我尝试过的解决方案之一,但希望有一个更简洁、更清洁的解决方案。不过看起来我别无选择。谢谢你的帮助! 我希望 setState 和 dispatch(来自 useReducer)函数能够返回新状态。 是的,那会很好,并且允许更简洁的代码。【参考方案2】:

设置状态是异步操作,不能像同步操作一样使用它。

因此,您必须使用 useEffect 钩子,该钩子在状态更改后运行。

import React, useState, useEffect from 'react';

const [productPage, setProductPage] = useState(1)
const [displayProducts, setDisplayProducts] = useState([])

const fetchProducts = async () => 
   setProductPage(productPage + 1)


useEffect(() => 
   const newProductsData = await fetch(`/api/getproducts?page=$productPage`)
   const newProductsArr = await newProductsData.json()
   setDisplayProducts(displayProducts.concat(newProductsArr))
, [productPage]); // <-- monitor productPage for changes

【讨论】:

以上是关于如何立即更新 react useState?的主要内容,如果未能解决你的问题,请参考以下文章

useState 函数没有立即更新[重复]

reactjs:一个不更新其变量的上下文组件函数; usestate 不能立即工作?

React useState总是落后1步[重复]

React useState:如何使用 onChange 输入和 OnClick 按钮更新我的 useState?

在useState中获得[react [duplicate]]后立即获取值]

如何在 React 中使用 useReducer 更新嵌套对象?