我的州没有从中获得价值 REACT

my state is not getting value into it REACT

我在代码中添加了两个处理程序。首先,输入邮件并启动 handleStart,然后从用户处获取用户名和密码,然后当按下按钮时,激活 handleFinish 并进行信息分配。 setEmail 状态有效,但密码和名称状态无效

  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [name, setName] = useState("");

  const history = useHistory();
  const url = "http://localhost:3002/register";

  const emailRef = useRef();
  const passwordRef = useRef();
  const usernameRef = useRef();

  const handleStart = () => {
        setEmail(emailRef.current.value);
      }
      const handleFinish = async (e) => {
        e.preventDefault();
        console.log("ref data", passwordRef.current.value,usernameRef.current.value) 
        //it works and shows values
        setPassword(passwordRef.current.value);
        setName(usernameRef.current.value);
        console.log("state data", email, password, name)
        //status values are empty except for email
        try {
          
          await axios.post(url, { email, name, password });
          history.push("/");
        } catch (err) { }
      }

和我的 return (HTML) 代码:

 {!email ? (
          <div className="input">
            <input type="email" placeholder="email address" ref={emailRef} />
            <button className="registerButton" onClick={handleStart}>
              Get Started
            </button>
          </div>
        ) : (
          <form className="input">
            <input type="username" placeholder="username" ref={usernameRef} />
            <input type="password" placeholder="password" ref={passwordRef} />
            <button className="registerButton" onClick={handleFinish}>
              Start
            </button>
          </form>
        )}

这是一个众所周知的问题,在这里解释了数千次,
状态更改在内部是异步的,这意味着我们不会立即在下一行获得更新状态,完成 setPasswordsetName 的执行需要时间,因此在设置状态后的下一行,console.log 将是旧值

console.log(passwordRef.current.value)
console.log(usernameRef.current.value)

这必须有值,并且登录到控制台但不是 passwordname 下面的行为是正确的,已知的,这里没有问题,

 console.log("state data", email, password, name)
 //status values are empty except for email

更好的是,下面的技巧对我来说总是有效,

 await axios.post(url, { email, usernameRef.current.value, passwordRef.current.value });

最好使用 useState 来存储和获取值和控制元素,而不是使用 ref

下面是使用状态的代码,可能对你有帮助:

const App = () => {
    const history = useHistory();
    const url = "http://localhost:3002/register";

    const [step, setStep] = useState(0)
    const [email, setEmail] = useState("")
    const [password, setPassword] = useState("")
    const [username, setUsername] = useState("")

    const handleStart = () => {
        setStep(1)
    }
    const handleFinish = async (e) => {
        e.preventDefault();
        console.log("data: ", email, password, username)
        try {
            await axios.post(url, { email, name, password });
            history.push("/");
        } catch (err) { }
    }

    return (
        step === 0 ? (
            <div className="input">
                <input
                    type="email"
                    value={email}
                    onChange={(e) => setEmail(e.target.value)}
                    placeholder="email address"
                />
                <button className="registerButton" onClick={handleStart}>
                    Get Started
                </button>
            </div>
        ) : (
            <form className="input">
                <input
                    type="username"
                    placeholder="username"
                    value={username}
                    onChange={(e) => setUsername(e.target.value)}
                />
                <input
                    type="password"
                    placeholder="password"
                    value={password}
                    onChange={() => setPassword(e.target.value)}
                />
                <button className="registerButton" onClick={handleFinish}>
                    Start
                </button>
            </form>
        )
    )
}

如果您希望activity根据电子邮件、密码、名称的值更改,使用 useEffect 可能是更好的选择。您可以调用 API 或执行任何 activity 作为这些值更改的结果。请找到以下代码 -

useEffect(() => {
    await axios.post(url, { email, name, password });
    history.push("/");
    return () => {
        // handle cancelling or other clean up
    }
}, [email, password, name]);