简体   繁体   English

反应挂钩useState不使用onSubmit更新

[英]React hook useState not updating with onSubmit

I'm currently experiencing an issue pushing the input field value to state onSubmit. 我目前遇到问题,将输入字段的值推到onSubmit状态。

codesandbox 代码框

I'm trying to set an input field value to the state so that I can use that value once the component is updated to redirect the user to another page. 我正在尝试将输入字段值设置为状态,以便在组件更新后将用户重定向到另一个页面时可以使用该值。 I tested the path manually and it works, but since the state is not updating synchronously, the redirect does not work. 我手动测试了该路径,它可以工作,但是由于状态无法同步更新,因此重定向不起作用。 I can render the input value on the page, but if I try to log it, it long undefined(for the first time) and the previous state on a second submit. 我可以在页面上呈现输入值,但是如果尝试记录该输入值,则很长的时间(第一次)是未定义的,并且在第二次提交时处于先前的状态。

import React, { useRef, useState } from "react";
import { db } from "../firebase";
import { Redirect } from "@reach/router";

function CreateProject(props) {
  const [id, setID] = useState(null);
  const colorRef = useRef(null);
  const projectNameRef = useRef(null);

  const handleSubmit = e => {
    e.preventDefault();
    const project = {
      name: projectNameRef.current.value,
      colors: [colorRef.current.value],
      colorName: colorNameRef.current.value,
      createdAt: new Date()
    };
    setID(projectNameRef.current.value);

    db.collection("users")
      .doc(`${props.user}`)
      .collection("projects")
      .doc(`${projectNameRef.current.value}`)
      .set({ ...project });
    e.target.reset();
  };


  return id ? (
    <Redirect from="/projects/new" to={`projects/:${id}`} noThrow />
  ) : (
    <div>
      <div>
        <h1>Create new selection</h1>
        <form onSubmit={handleSubmit}>
          <label>Color</label>
          <input ref={colorNameRef} type="text" name="colorName" />
          <label>Project Name</label>
          <input ref={projectNameRef} type="text" name="projectName" required />
          <button type="submit">Submit</button>
        </form>
      </div>
    </div>
  );
}

export default CreateProject;

react: 16.8.6 反应:16.8.6

That's the way react hooks useState works, to do something after a state change you should perform it inside a useEffect hook, like the following: 这是反应挂钩useState起作用的方式,要在状态更改后执行某些操作,您应该在useEffect挂钩内执行它,如下所示:

useEffect(() => {
  if (id) {
    console.log(id);
    projectNameRef.current.value = ''
  }
}, [id])

This effect will run every time the id value changes (and in the first render) so you could add your logic there and perform your desired actions based on the state change. 每当id值更改时(以及在第一个渲染中),都会运行此效果,因此您可以在其中添加逻辑并根据状态更改执行所需的操作。

I think your use of ref here is inappropriate and may be causing the issue. 我认为您在此处使用ref是不合适的,可能会导致问题。 I would rewrite your function like this. 我会这样重写您的函数。

function CreateProject() {
  const [id, setID] = useState(null);
  const [shouldRedirect, setShouldRedirect] = useState(false);

  const handleSubmit = e => {
    e.preventDefault();
    setShouldRedirect(true);
  };

  const handleChange = (e) => {
    setID(e.target.value);
  }

  return shouldRedirect ? (
    <Redirect from="/projects/new" to={`projects/:${id}`} noThrow />
  ) : (
    <div>
      <div>
        <h1>Create new selection</h1>
        <form onSubmit={handleSubmit}>
          <label>Project Name</label>
          <input onChange={handleChange} type="text" name="projectName" required />
          <button type="submit">Submit</button>
        </form>
      </div>
    </div>
  );

In this way your state is always being updated and therefore so is your redirect URL. 这样,您的状态将始终被更新,因此重定向URL也将被更新。 When you submit, you simply tell the component it should now submit with the current ID. 提交时,您只需告诉组件现在应使用当前ID提交。

You can see how this works from the React documentation. 您可以从React文档中了解其工作原理。

You may even be able to replace the conditional render with a functional call to history.push using withRouter . 您甚至可以使用withRouter对功能history.push调用来替换条件渲染。 See advice on this question. 请参阅有关此问题的建议。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM