延迟状态变化

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;