如何立即更新反应useState?

时间:2020-06-26 00:28:43

标签: reactjs react-hooks next.js

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

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

   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,我不确定这是否会有所作为。我不能使用普通变量,因为它们会在每个渲染器上重置。

2 个答案:

答案 0 :(得分:1)

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

那你该怎么办?您有两种选择。

它使用useEffect的那个,它将查看productPage是否发生更改(每次执行该函数=重新渲染),如果更改,它将获取数据并使用setDisplayProducts进行更改。用displayProducts中的新值重新渲染组件。如果您打算采用其他方式来更新productPage,并且希望它们也触发获取,则很好。

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));
};

答案 1 :(得分:1)

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

因此,您必须使用 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