延迟状态变化
Delay in the state change
当我按下“提交”按钮时,控制台显示“成功”,即使输入为空,当我再次按下时,它最终显示“错误”。
如何更改代码,以便在我第一次按下按钮时控制台显示“错误”?
import React, { useState } from "react";
import "./App.css";
function App() {
const [input, setInput] = useState("");
const [error, setError] = useState(false);
const submitHandler = (e) => {
e.preventDefault();
if (input === "") {
setError(true);
}
if (error) {
console.log("error");
return;
}
console.log("success");
};
return (
<div className="App">
<form onSubmit={submitHandler}>
<input onChange={(e) => setInput(e.target.value)}></input>
<button type="submit">Submit</button>
</form>
</div>
);
}
export default App;
在 React 中设置状态是一个异步函数。
这意味着当您设置状态并在它后面放置一个 console.log
时,就像在您的示例中一样,console.log
函数在状态实际完成更新之前运行。
这就是我们拥有 useEffect
的原因,这是一个内置的 React 钩子,当其中一个依赖项发生变化时会激活回调。
像这样:
import { useState, useEffect } from 'react';
const [state, setState] = useState();
useEffect(() => {
// Actions we want to happen when the state has been fully updated.
}, [state]);
对于您的示例,它可能如下所示:
const submitHandler = (e) => {
e.preventDefault();
if (input === "") {
setError(true);
}
}
useEffect(() => {
// No need for === true
if (error) {
console.log("error");
return;
}
console.log("success");
}, [error])
,您应该首先检查提交是否针对另一个状态或参考 (useRef
)。
function App() {
const [isFirstSubmit, setIsFirstSubmit] = useState(true);
const submitHandler = (e) => {
e.preventDefault();
if (isFirstSubmit) {
console.log("error");
setIsFirstSubmit(false);
}
};
return <form onSubmit={submitHandler}>...</form>;
}
再看状态声明:
const [error, setError] = useState(false);
调用 setError
不可能改变 error
,因为它是 const
。语言不允许。
发生的事情是 useState
挂钩将 return 传递给 setError
的值 下一次组件呈现 。
如果你稍微调整一下你的 handleSubmit
逻辑,考虑到它知道什么时候调用 setError(true)
,你可以达到预期的结果:
const submitHandler = (e) => {
e.preventDefault();
if (input === "") {
setError(true);
console.log("error");
return;
}
console.log("success");
};
我所做的只是删除了两行代码。
您可以将代码更新为
if (input === "") {
setError(true);
console.log("error");
return;
}
console.log("success");
所以首先 if 你可以处理错误条件,然后它就会成功。
与设置状态的异步机制无关。这都是关于闭包的。在处理函数中,error
的值将等于它在最后一次渲染期间的值(在实际创建此函数时)。
setError(true)
的作用是安排组件重新渲染 error
的新值。 error
的值将在调用 setError
后的下一次渲染期间变为 true
。
假设您只想在提交时看到相关消息,则根本不需要错误状态。
import * as React from "react";
import "./App.css";
function App() {
const [input, setInput] = React.useState("");
const submitHandler = (e) => {
e.preventDefault();
console.log(input === "" ? "error" : "success")
};
return (
<div className="App">
<form onSubmit={submitHandler}>
<input onChange={(e) => setInput(e.target.value)}></input>
<button type="submit">Submit</button>
</form>
</div>
);
}
export default App;
当我按下“提交”按钮时,控制台显示“成功”,即使输入为空,当我再次按下时,它最终显示“错误”。
如何更改代码,以便在我第一次按下按钮时控制台显示“错误”?
import React, { useState } from "react";
import "./App.css";
function App() {
const [input, setInput] = useState("");
const [error, setError] = useState(false);
const submitHandler = (e) => {
e.preventDefault();
if (input === "") {
setError(true);
}
if (error) {
console.log("error");
return;
}
console.log("success");
};
return (
<div className="App">
<form onSubmit={submitHandler}>
<input onChange={(e) => setInput(e.target.value)}></input>
<button type="submit">Submit</button>
</form>
</div>
);
}
export default App;
在 React 中设置状态是一个异步函数。
这意味着当您设置状态并在它后面放置一个 console.log
时,就像在您的示例中一样,console.log
函数在状态实际完成更新之前运行。
这就是我们拥有 useEffect
的原因,这是一个内置的 React 钩子,当其中一个依赖项发生变化时会激活回调。
像这样:
import { useState, useEffect } from 'react';
const [state, setState] = useState();
useEffect(() => {
// Actions we want to happen when the state has been fully updated.
}, [state]);
对于您的示例,它可能如下所示:
const submitHandler = (e) => {
e.preventDefault();
if (input === "") {
setError(true);
}
}
useEffect(() => {
// No need for === true
if (error) {
console.log("error");
return;
}
console.log("success");
}, [error])
useRef
)。
function App() {
const [isFirstSubmit, setIsFirstSubmit] = useState(true);
const submitHandler = (e) => {
e.preventDefault();
if (isFirstSubmit) {
console.log("error");
setIsFirstSubmit(false);
}
};
return <form onSubmit={submitHandler}>...</form>;
}
再看状态声明:
const [error, setError] = useState(false);
调用 setError
不可能改变 error
,因为它是 const
。语言不允许。
发生的事情是 useState
挂钩将 return 传递给 setError
的值 下一次组件呈现 。
如果你稍微调整一下你的 handleSubmit
逻辑,考虑到它知道什么时候调用 setError(true)
,你可以达到预期的结果:
const submitHandler = (e) => {
e.preventDefault();
if (input === "") {
setError(true);
console.log("error");
return;
}
console.log("success");
};
我所做的只是删除了两行代码。
您可以将代码更新为
if (input === "") {
setError(true);
console.log("error");
return;
}
console.log("success");
所以首先 if 你可以处理错误条件,然后它就会成功。
与设置状态的异步机制无关。这都是关于闭包的。在处理函数中,error
的值将等于它在最后一次渲染期间的值(在实际创建此函数时)。
setError(true)
的作用是安排组件重新渲染 error
的新值。 error
的值将在调用 setError
后的下一次渲染期间变为 true
。
假设您只想在提交时看到相关消息,则根本不需要错误状态。
import * as React from "react";
import "./App.css";
function App() {
const [input, setInput] = React.useState("");
const submitHandler = (e) => {
e.preventDefault();
console.log(input === "" ? "error" : "success")
};
return (
<div className="App">
<form onSubmit={submitHandler}>
<input onChange={(e) => setInput(e.target.value)}></input>
<button type="submit">Submit</button>
</form>
</div>
);
}
export default App;