【问题标题】:Delay in the state change状态变化延迟
【发布时间】:2021-10-06 10:46:13
【问题描述】:

当我按下“提交”按钮时,即使输入为空,控制台也会显示“成功”,当我再次按下时,它最终会显示“错误”。

如何更改代码,以便在我第一次按下按钮时控制台会显示“错误”?

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;

【问题讨论】:

    标签: reactjs use-state


    【解决方案1】:

    再看状态声明:

    const [error, setError] = useState(false);
    

    调用setError 不会改变error,因为它是const。语言不允许。

    发生的情况是useState 挂钩将返回传递给setError 的值组件下次渲染时

    如果你稍微调整你的handleSubmit逻辑,考虑到它知道什么时候调用setError(true),你就可以达到预期的结果:

      const submitHandler = (e) => {
        e.preventDefault();
        if (input === "") {
          setError(true);
          console.log("error");
          return;
        }
        console.log("success");
      };
    

    我所做的只是删除了两行代码。

    【讨论】:

      【解决方案2】:

      State change is async,您应该先根据另一个状态或参考 (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>;
      }
      

      【讨论】:

        【解决方案3】:

        在 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])
        

        【讨论】:

          【解决方案4】:

          您可以将代码更新为

          if (input === "") {
            setError(true);
            console.log("error");
            return;
          }
          
          console.log("success");
          

          所以在第一个 if 中,您可以处理错误情况,之后它将成功。

          【讨论】:

            【解决方案5】:

            与设置状态的异步机制无关。这都是关于闭包的。在处理函数中,error 的值将等于它在上次渲染期间(实际创建此函数时)的值。

            setError(true) 的作用是使用新值error 安排组件重新渲染。在调用 setError 之后的下一次渲染期间,error 的值将是 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;
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2013-02-03
              • 1970-01-01
              • 1970-01-01
              • 2021-11-06
              • 1970-01-01
              • 1970-01-01
              • 2011-11-17
              • 2023-03-21
              相关资源
              最近更新 更多