【问题标题】:How to update react useState without delay?如何立即更新 react useState?
【发布时间】: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 吗?在功能范围内做你想执行的任务,完成后设置状态。

标签: reactjs react-hooks next.js


【解决方案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

【讨论】:

    猜你喜欢
    • 2022-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-18
    • 2021-05-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多