我有一个问题,我不明白为什么钩子返回 undefined :
import React, { useEffect, useState } from 'react';
function App(){
const [globalVariable, setGlobalVariable] = useState();
useEffect(()=>{
const test = 5
console.log(test) // return 5
setGlobalVariable(test)
console.log(globalVariable) // return undefined
},[]);
return (
<div>
</div>
);
}
export default App;
Run Code Online (Sandbox Code Playgroud)
我该怎么做才能直接为 globalVariable 设置新值?
Ren*_*tto 10
正如其他成员所提到的,setState 在基于队列的系统中异步运行。这意味着如果要执行状态更新,则此更新将堆积在队列上。但是,它不返回 Promise,因此您不能使用 a.then或 a wait。因此,我们需要意识到在 React 中操作状态时可能出现的问题。
假设我们有:
// PROBLEM # 1
export function Button() {
const [count, setCount] = useState(0);
function increment() {
setCount(count + 1);
console.log(count); // returns 0
}
return (
<button onClick={increment}>Increment<\button>
)
}
Run Code Online (Sandbox Code Playgroud)
这基本上与您遇到的问题相同。由于 setCount 是异步的,因此console.log将返回更新之前的值(此处为 0)。在您的情况下,它将返回,undefined因为您没有在 useState 挂钩中传递任何初始状态。您所做的另一件事是从钩子内部触发状态更改useEffect,但这对于当前的问题并不重要。
要解决此问题,一个好的做法是将新状态存储在另一个变量中,如下所示:
// SOLUTION TO PROBLEM # 1
export function Button() {
const [count, setCount] = useState(0);
function increment() {
const newCountValue = count + 1;
setCount(newCountValue);
console.log(newCountValue); // returns 1
}
return (
<button onClick={increment}>Increment<\button>
)
}
Run Code Online (Sandbox Code Playgroud)
这基本上回答了你的问题。
但是,在其他情况下,状态更新可能不会按预期运行。了解这些场景以避免可能出现的错误非常重要。例如,假设我们连续多次更新给定状态,例如:
// PROBLEM # 2
export function Button() {
const [count, setCount] = useState(0);
function increment() {
setCount(count + 1);
setCount(count + 1);
setCount(count + 1);
console.log(count); // returns 0, but the final state will be 1 (not 3)
}
return (
<button onClick={increment}>Increment<\button>
)
}
Run Code Online (Sandbox Code Playgroud)
这里,console.log仍然返回 0,原因与问题 #1 中描述的相同。但是,如果您在应用程序中的某处使用count状态,您将看到事件后的最终值为onClick1,而不是 3。
以下是解决此问题的方法:
// SOLUTION TO PROBLEM # 2
export function Button() {
const [count, setCount] = useState(0);
function increment() {
setCount((oldState) => oldState + 1);
setCount((oldState) => oldState + 1);
setCount((oldState) => oldState + 1);
console.log(count); // returns 0, but the final state will be 3
}
return (
<button onClick={increment}>Increment<\button>
)
}
Run Code Online (Sandbox Code Playgroud)
通过将函数传递给 setState,新状态是使用队列上的前一个值而不是初始值来计算的。
作为最后一个例子,假设我们在尝试改变状态后立即调用一个函数,但该函数取决于状态值。由于操作是异步的,该函数将使用“旧”状态值,就像问题#1 中一样:
// PROBLEM # 3
export function Button() {
const [count, setCount] = useState(0);
onCountChange() {
console.log(count); // returns 0;
}
function increment() {
setCount(count + 1);
onCountChange();
}
return (
<button onClick={increment}>Increment<\button>
)
}
Run Code Online (Sandbox Code Playgroud)
onCountChange请注意,在这个问题中,我们有一个依赖于外部变量 ( )的函数count。通过外部我的意思是这个变量没有在 的范围内声明onCountChange。他们实际上是兄弟姐妹(都在Button范围内)。现在,如果你熟悉“纯函数”、“幂等”和“副作用”的概念,你就会意识到我们这里遇到的是副作用问题——我们希望在状态改变后发生一些事情。
粗略地说,每当你需要处理 React 中的一些副作用时,都是通过 useEffect 钩子来完成的。因此,要解决第三个问题,我们可以简单地执行以下操作:
// SOLUTION TO PROBLEM # 3
export function Button() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log(count); // returns 0;
}, [count]);
function increment() {
setCount(count + 1);
}
return (
<button onClick={increment}>Increment<\button>
)
}
Run Code Online (Sandbox Code Playgroud)
在上面的解决方案中,我们将 的内容移至onCountChangeuseEffect 并添加count为依赖项,因此每当它发生变化时,效果就会被触发。
两件事情:
useState有一个初始值,默认为未定义。const [globalVariable, setGlobalVariable] = useState(123); // initial value set to 123
Run Code Online (Sandbox Code Playgroud)
setGlobalVariable不是同步操作。改变它不会globalVariable立即变异。范围中的值将保持不变,直到下一个渲染阶段。| 归档时间: |
|
| 查看次数: |
32529 次 |
| 最近记录: |