如果状态已更新,则在反应挂钩中提交按钮后不会重新呈现

Doesn't re-render after button submit in react hooks if state updated

单击按钮后,将验证字段并将错误分配给状态变量。

但是当在 onSubmitClick 中更新状态时,render/view 不会刷新以显示错误。

我已经通过记录错误字段来交叉检查 TextField 组件,但错误似乎没有出现..

import React, { useState } from "react";

const Register = () => {
  const [user, setUser] = useState({
    name: "",
    email: "",
    password: "",
  });

  const setData = (type) => e => {
    user[type] = e.target.value;
    setUser(user);
  };

  const onSubmitClick = e => {
    // Check if fields are empty
    if (!user.name) {
      user.nameError = "Name field cannot be left blank !!";
    }

    if (!user.email) {
      user.emailError = "Email field cannot be left blank !!";
    }

    if (!user.password) {
      user.passwordError = "Password field cannot be left blank !!";
    }

    // Setting the error here
    setUser(user);
  };

  return (
    <div>
      <TextField value={user.name} error={user.nameError} label="Name" onChange={setData("name")} />
      <TextField value={user.email} error={user.emailError} label="Email" onChange={setData("email")} />
      <TextField value={user.password} error={user.passwordError} abel="Password" onChange={setData("password")} />
      <Button content="REGISTER" onClick={onSubmitClick} />
    </div>
  );
};

export default Register;

所以基本上在提交时如果字段有错误我需要显示错误。

我不明白为什么你需要发送额外的类型,你可以通过从输入框中获取名称来完成。在您的情况下,您没有在 setData 中设置正确的状态,即它没有改变 userData。你可以这样做: 在您的情况下,您可以这样做:

    setUser({...user,user[type] : e.target.value}); // ensure rest value will remain there and update existing value

import React, { useState } from "react";
import { render } from 'react-dom';



const Register = () => {
  const [user, setUser] = useState({
    name: "",
    email: "",
    password: "",
  });

  const setData =  e => {
    console.log(e.target.name)

    console.log(user)
    setUser({...user,[e.target.name] : e.target.value});
  };

  const onSubmitClick = e => {
    // Check if fields are empty
    if (!user.name) {
      user.nameError = "Name field cannot be left blank !!";
    }

    if (!user.email) {
      user.emailError = "Email field cannot be left blank !!";
    }

    if (!user.password) {
      user.passwordError = "Password field cannot be left blank !!";
    }
  console.log(user)
    // Setting the error here
    setUser(user);
  };

  return (
    <div>
      <input value={user.name} error={user.nameError} name="name" label="Name" onChange={(e) => setData(e)} />
      <input value={user.email} error={user.emailError} name="email" label="Email" onChange={(e) => setData(e)} />
      <input value={user.password} error={user.passwordError} name="password" label="Password" onChange={(e) => setData(e)} />
      <button content="REGISTER" onClick={onSubmitClick} >Submit</button>
    </div>
  );
};

export default Register;


render(<Register />, document.getElementById('root'));

这里正在工作 link : https://stackblitz.com/edit/react-fbuzph

您正在改变 user state 对象并使用 相同的对象引用 设置 state,这就是为什么组件不是 re-rendering 在更新状态之前总是从当前 state 构造一个新对象是一个好习惯。

const setData = (type) => e => {
  setUser(prevState => ({
    ...prevState,
    [type]: e.target.value,
  }));
};

const onSubmitClick = e => {
  // destruct the current state and make a new object of it
  // now we can mutate it and assign it to state
  const updatedState = { ...user };
  // Check if fields are empty
  if (!updatedState.name) {
    updatedState.nameError = "Name field cannot be left blank !!";
  }

  if (!updatedState.email) {
    updatedState.emailError = "Email field cannot be left blank !!";
  }

  if (!updatedState.password) {
    updatedState.passwordError = "Password field cannot be left blank !!";
  }

  setUser(updatedState);
};

您正在更新引用中的同一个 state 对象,而不是完全创建一个新状态。通过接收新道具或新状态对象仅 re-renders 您的组件做出反应。

查看沙盒和 code-below 了解如何添加和清除提交时的错误:https://codesandbox.io/s/blissful-river-ou4o0

Register.js

import React, { useState } from "react";
import ReactDOM from "react-dom";
import TextField from "./TextField";

import "./styles.css";

const Register = () => {
  const [user, setUser] = useState({
    name: "",
    email: "",
    password: ""
  });

  const setData = e => {
    const updatedUser = { ...user };

    updatedUser[e.target.name] = e.target.value;
    setUser(updatedUser);
  };

  const onSubmitClick = e => {
    // Check if fields are empty
    const updatedUser = { ...user };

    updatedUser.nameError = !updatedUser.name
      ? "Name field cannot be left blank !!"
      : "";

    updatedUser.emailError = !updatedUser.email
      ? "Email field cannot be left blank !!"
      : "";

    updatedUser.passwordError = !updatedUser.password
      ? "Password field cannot be left blank !!"
      : "";

    setUser(updatedUser);
  };

  return (
    <div>
      <TextField
        value={user.name}
        error={user.nameError}
        name="name"
        label="Name"
        onChange={setData}
      />
      <TextField
        value={user.email}
        error={user.emailError}
        name="email"
        label="Email"
        onChange={setData}
      />
      <TextField
        value={user.password}
        error={user.passwordError}
        name="password"
        label="Password"
        onChange={setData}
      />
      <button content="REGISTER" onClick={onSubmitClick}>
        Submit
      </button>
    </div>
  );
};

export default Register;

const rootElement = document.getElementById("root");
ReactDOM.render(<Register />, rootElement);

TextField.js

import React from "react";

const TextField = props => {
  return (
    <div>
      <label>{props.label}</label>
      <input value={props.value} name={props.name} onChange={props.onChange} />
      {props.error ? <p>{props.error}</p> : null}
    </div>
  );
};

export default TextField;