#javascript #reactjs
#javascript #reactjs
Вопрос:
У меня есть приложение react, в котором есть форма с некоторыми полями вместе с проверкой. Однако проверки не работают так, как я ожидаю, что они будут работать. Код приведен ниже:
state = {
user: null,
errors: {}
}
onSubmitHandler = e => {
e.preventDefault();
//Check if first Name is returned empty
if (this.state.user.name.trim().length === 0) {
this.setState({
errors: {
...this.state.errors,
name: "This field is required"
}
});
}
//Check if last name is returned empty
if (this.state.user.surname.trim().length === 0) {
this.setState({
errors: {
...this.state.errors,
surname: "This field is required"
}
});
return;
}
}
Теперь, когда я не предоставляю оба поля ввода и оставляю их пустыми, я ожидаю, что в моем состоянии будут отображаться оба сообщения об ошибках, т.е. errors: {name: "This field is required", surname: "This field is required"}
Но я получаю только недавнюю ошибку, которая относится к фамилии. Итак, мой результат выглядит так errors: {surname: "This field is required"}
Почему оно переопределяет первое сообщение об ошибке? Любая помощь будет оценена. Код для поля ввода не отображается, поскольку они являются просто тегами ввода с обработчиком событий onChange.
Ответ №1:
Два вызова в будут объединены вместе. this.setState
onSubmitHandler
Думайте о setState() как о запросе, а не о немедленной команде для обновления компонента. Для лучшей воспринимаемой производительности React может задержать его, а затем обновить несколько компонентов за один проход. React не гарантирует, что изменения состояния будут применены немедленно.
setState() не всегда немедленно обновляет компонент. Это может привести к пакетной передаче или отложению обновления на более поздний срок. Это делает чтение this.state сразу после вызова setState() потенциальной ловушкой
Поэтому, когда вы это делаете ...this.state.errors
, this.state.errors
в обоих if
блоках ссылается на пустой объект. В результате вы видите только surname
ключ в errors
объекте в состоянии.
Вы можете исправить эту проблему, скопировав this.state.errors
объект, добавив ключи в скопированный объект, а затем передать этот скопированный объект this.setState
.
onSubmitHandler = e => {
e.preventDefault();
// clone the "errors" object
const errors = { ...this.state.errors };
//Check if first Name is returned empty
if(this.state.user.name.trim().length === 0) {
errors.name = "This field is required";
}
//Check if last name is returned empty
if(this.state.user.surname.trim().length === 0) {
errors.surname = "This field is required";
}
this.setState({ errors });
}
Ответ №2:
Это потому, что во втором распространении все еще используется старое значение this.state.errors, поскольку оно еще не изменилось. Оба setStates могут (в вашем случае: определенно были) обновлять состояние позже, после выполнения onSubmitHandler .
Читайте также https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous
Измените аргументы setState на функции, которые автоматически используют последнее состояние:
onSubmitHandler = e => {
e.preventDefault();
//Check if first Name is returned empty
if (this.state.user.name.trim().length === 0) {
this.setState(state => ({
errors: {
...state.errors,
name: "This field is required"
}
}));
}
//Check if last name is returned empty
if (this.state.user.surname.trim().length === 0) {
this.setState(state => ({
errors: {
...state.errors,
surname: "This field is required"
}
}));
return;
}
}