如何立即更新 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?的主要内容,如果未能解决你的问题,请参考以下文章
reactjs:一个不更新其变量的上下文组件函数; usestate 不能立即工作?
React useState:如何使用 onChange 输入和 OnClick 按钮更新我的 useState?