React hook useState 不使用 onSubmit 更新

IT技术 reactjs react-router react-hooks onsubmit reach-router
2021-05-10 17:34:01

我目前在将输入字段值推送到 onSubmit 状态时遇到问题。

代码沙盒

我正在尝试将输入字段值设置为状态,以便在组件更新后我可以使用该值将用户重定向到另一个页面。我手动测试了路径并且它可以工作,但是由于状态不是同步更新,因此重定向不起作用。我可以在页面上呈现输入值,但是如果我尝试记录它,它会长时间未定义(第一次)和第二次提交时的先前状态。

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

2个回答

这就是React钩子useState 的工作方式,要在状态更改后执行某些操作,您应该在useEffect钩子中执行它,如下所示:

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

每次id值更改时(以及在第一次渲染中),此效果都会运行,因此您可以在此处添加逻辑并根据状态更改执行所需的操作。

我认为您对ref此处的使用是不恰当的,并且可能是导致问题的原因。我会像这样重写你的函数。

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>
  );

通过这种方式,您的状态始终在更新,因此您的重定向 URL 也在更新。当您提交时,您只需告诉组件它现在应该使用当前 ID 提交。

您可以从 React 文档中了解这是如何工作的。

您甚至可以history.push使用using的函数调用来替换条件渲染withRouter请参阅有关此问题的建议。