如果状态已更新,则不会在React钩子中提交按钮后重新渲染

时间:2019-07-14 07:23:14

标签: reactjs react-hooks

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

但是,当状态在 onSubmitClick 中更新时,渲染/视图不会刷新以显示错误。

我通过记录错误字段来交叉检查了 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;

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

3 个答案:

答案 0 :(得分:2)

您要对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);
};

答案 1 :(得分:1)

我不明白为什么您需要发送额外的类型,您可以简单地通过从输入框中获取名称来做到这一点。而且在您的情况下,您没有在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'));

这是有效的链接:https://stackblitz.com/edit/react-fbuzph

答案 2 :(得分:1)

您正在对引用中的同一state对象进行更新,而不是完全一起创建新状态。 React只能通过接收新道具或新状态对象来重新渲染您的组件。

有关如何在提交时添加和清除错误的信息,请参见沙盒和下面的代码: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;