setState компонентов функции реагирования, не применяющих изменения

У меня есть компонент функции реакции, который возвращает простую форму. Все, что я хочу сделать, это очистить предыдущие ошибки полей при отправке, а затем снова проверить поля. удивительно, что первый вызов setState не применяет изменений, но остальные работают нормально.

вот весь код:

import React from "react";
import { TextField, Button } from "@material-ui/core";

export default function EditPresonalInfo() {
  const [fields, setFields] = React.useState({
    username: "",
    usernameHelper: "",
    usernameError: false,
    name: "",
    nameHelper: "",
    nameError: false,
  });

  const submitForm = (e) => {
    e.preventDefault();

    setFields({
      ...fields,
      usernameError: false,
      usernameHelper: "",
      nameError: false,
      nameHelper: "",
    });

    if (fields.username.length < 4) {
      setFields({
        ...fields,
        usernameHelper: "use at least 4 characters",
        usernameError: true,
      });
      return;
    }

    if (fields.name.length < 2) {
      setFields({
        ...fields,
        nameHelper: "use at least 2 characters",
        nameError: true,
      });
      return;
    }
  };

  const handleChange = (fieldName) => (event) => {
    setFields({
      ...fields,
      [fieldName]: event.target.value,
    });
  };

  return (
    <form onSubmit={submitForm}>
      <TextField
        label="username"
        onChange={handleChange("username")}
        error={fields.usernameError}
        value={fields.username}
        helperText={fields.usernameHelper}
      />
      <TextField
        label="name"
        onChange={handleChange("name")}
        error={fields.nameError}
        value={fields.name}
        helperText={fields.nameHelper}
      />
      <Button type="submit">submit</Button>
    </form>
  );
}

может кто-нибудь помочь мне с тем, что мне не хватает и что не так?


person fmatt    schedule 10.09.2020    source источник
comment
comment
Я бы предпочел использовать обычный синтаксис (import {useState} из 'response'; а затем useState ()) для начала. Где другие звонки, которые вы упомянули?   -  person David Thery    schedule 10.09.2020
comment
Ваш fields не обновляется непосредственно в начале вашей функции submitForm, он будет обновлен в конце жизненного цикла. Поэтому, когда вы позже будете использовать fields в функции, оно останется «исходным» значением.   -  person Nico_    schedule 10.09.2020
comment
@DavidThery Я имею в виду вызовы в операторах if, которые правильно устанавливают вспомогательные тексты   -  person fmatt    schedule 10.09.2020
comment
@Nico_, вы имеете в виду, что это из-за использования ... полей, а поля еще не обновлены?   -  person fmatt    schedule 10.09.2020
comment
@fmatt Да, попробуйте console.log ваш fields, вы увидите, что он не обновляется (до следующего рендера).   -  person Nico_    schedule 10.09.2020
comment
@Nico_ вот и все! большое спасибо . поэтому, если я правильно понял, состояния обновляются при рендеринге, а не в setState.   -  person fmatt    schedule 10.09.2020


Ответы (4)


Вам не нужно устанавливать состояние для каждой проверки. Я думаю, что для этого сценария лучше всего сначала создать новое состояние на основе проверок, после чего вы установите состояние.

const submitForm = (e) => {
  e.preventDefault();

  const newFields = { ...fields };

  if (fields.username.length < 4) {
    newFields["usernameHelper"] = "use at least 4 characters";
    newFields["usernameError"] = true;
  } else {
    newFields["usernameHelper"] = "";
    newFields["usernameError"] = false;
  }

  if (fields.name.length < 2) {
    newFields["nameHelper"] = "use at least 2 characters";
    newFields["nameError"] = true;
  } else {
    newFields["nameHelper"] = "";
    newFields["nameError"] = false;
  }

  setFields(newFields);
};

 Изменить практическую сосну-rkho0

person 95faf8e76605e973    schedule 10.09.2020
comment
Благодарность ! это было действительно полезно после того, как я понял свою ошибку - person fmatt; 10.09.2020

это сработало для меня

 const submitForm = (e) => {
    e.preventDefault();
    let usernameHelper = "";
    let usernameError = false;
    let nameError = false;
    let nameHelper = "";

    if (fields.username.length < 4) {
      usernameHelper = "use at least 4 characters";
      usernameError = true;
    }
    if (fields.name.length < 2) {
      nameHelper = "use at least 2 characters";
      nameError = true;
    }
    setFields({
      ...fields,
      usernameError: usernameError,
      usernameHelper: usernameHelper,
      nameError: nameError,
      nameHelper: nameHelper,
    });
  };
person That Guy Kev    schedule 10.09.2020

Насколько я понимаю, вы хотите применить некоторую проверку к своей форме и, следовательно, вы уже используете MaterialUI, я предлагаю вам перейти по этой ссылке https://react-hook-form.com/get-started#Applyvalidation. Там вы найдете лучшие практики и более простые реализации.

person That Guy Kev    schedule 10.09.2020
comment
спасибо за вашу помощь, но я учусь реагировать как новичок, и мне действительно любопытно посмотреть, что происходит в этом методе - person fmatt; 10.09.2020
comment
потерять доход; в каждом операторе if в java-скрипте код не выполняется строка покупки строки, поэтому ваша функция on Submit может выполнять один из операторов if и завершаться до выполнения остальной части кода (скорее всего, первого setFields) - person That Guy Kev; 10.09.2020
comment
Правильно, я тоже ошибся. потому что возникло несколько ошибок, только одна появилась - person fmatt; 10.09.2020

Я ошибочно использовал setFields для изменения fields в данный момент. Вместо этого это можно сделать явно так

const submitForm = (e) => {
    e.preventDefault();

    fields.nameError= false
    fields.usernameError= false
    fields.nameHelper= ""
    fields.usernameHelper= ""

    if (fields.name.length < 2) {
      fields.nameHelper = "use at least 2 characters";
      fields.nameError = true;
    }

    if (fields.username.length < 4) {
      fields.usernameHelper = "use at least 4 characters";
      fields.usernameError = true;
    }

    setFields({
      ...fields
    })
  };
person fmatt    schedule 10.09.2020