反应钩子 useState 不使用 onSubmit 更新

Posted

技术标签:

【中文标题】反应钩子 useState 不使用 onSubmit 更新【英文标题】:React hook useState not updating with onSubmit 【发布时间】:2019-09-15 05:07:26 【问题描述】:

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

codesandbox

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

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;

反应:16.8.6

【问题讨论】:

它是否重定向?还是新的 url 缺少正确的 id? 它正在重定向,但只是重定向到“/projects”而不是“projects/InputValue” 【参考方案1】:

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

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

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

【讨论】:

当用useState改变状态时,react不会等待它继续,它是异步的,所以这就是为什么用useEffect钩子监听状态变化是react的方式16. More info about the useEffect hook. 谢谢 :) ,在重构和添加 useEffect 之后,它运行正常,但它没有重定向到它应该重定向的位置,经过多次尝试后,我发现我在重定向中有错误,我被重定向到=projects/:$id 而不是=projects/$id【参考方案2】:

我认为您在此处使用 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 提交。

You can see how this works from the React documentation.

您甚至可以使用withRouter 调用history.push 来替换条件渲染。 See advice on this question.

【讨论】:

以上是关于反应钩子 useState 不使用 onSubmit 更新的主要内容,如果未能解决你的问题,请参考以下文章

如何在反应中使用带有useState钩子的回调[重复]

在 useState 钩子中反应设置状态

反应useState钩子,用函数调用setState [重复]

反应钩子useState()的真正奇怪的行为

为啥反应钩子使用状态显示错误消息

为啥在反应的“useState”钩子中一遍又一遍地设置初始状态