У меня есть некоторые проблемы с кодом React. Внутри моего App.jsx
я написал логику с деструктуризацией объекта, полученной из тега jsx, и без него:
<input
name = "fName"
placeholder = "First Name"
onChange = {handleChangeEvent}
value = {fullName.fName}
/>
<input
name = "lName"
placeholder = "Last Name"
onChange = {handleChangeEvent}
value = {fullName.lName}
/>
Вот код с способом деструктуризации:
function handleChangeEvent(event) {
const { name, value } = event.target;
setFullName((preValue) => {
if (name === "fName") {
return {
fName: value,
lName: preValue.lName,
};
} else if (name === "lName") {
return {
fName: preValue.fName,
lName: value,
};
}
});
}
Хотя это код без деструктуризации
function handleChangeEvent(event) {
setFullName((preValue) => {
if (event.target.name === "fName") {
return {
fName: event.target.value,
lName: preValue.lName,
};
} else if (event.target.name === "lName") {
return {
fName: preValue.fName,
lName: event.target.value,
};
}
});
}
Обратите внимание, что я пытался написать код с той же логикой. Однако, хотя первый вариант работает, во втором мой код не работает и начинает давать сбой, показывая эту ошибку:
TypeError
Cannot read properties of null (reading 'name')
eval
/src/components/App.jsx:11:23
8 |
9 | function handleChangeEvent(event) {
10 | setFullName((preValue) => {
> 11 | if (event.target.name === "fName") {
| ^
12 | return {
13 | fName: event.target.value,
14 | lName: preValue.lName,
Я ожидаю, что это сработает, даже если я не использую деструктуризацию.
@jabaa …и на самом деле объект event
модифицируется, поскольку он перемещается вверх по дереву DOM, пока не достигнет вершины; перед повторной визуализацией компонента и вызовом функции обновления состояния. Я немного удивлен, что event.target
становится null
(а не просто event.currentTarget
, который меняется во время всплытия), но это также может быть специфично для синтетических событий React.
Я думаю, что ваша проблема связана с масштабом. Просто избавьтесь от объявления функции setFullName и сохраните тело функции.
@hippoman Это не объявление функции. Это вызов функции.
Кажется, вы используете более старую версию React, и событие было обнулено и возвращено в пул событий. Я считаю, что это изменилось в React 17. Вызовите event.persist()
во второй реализации, если вы хотите, чтобы объект события передавался до тех пор, пока не будет обработано обновление состояния React.
Это не имеет ничего общего с деструктуризацией. Это важно только при доступе к объекту.
В первом фрагменте значения name
и value
копируются до вызова setFullName
. Во втором примере доступ к объекту event
осуществляется после вызова setFullName
. Объект является изменяемым, и вы получите другое поведение, если объект будет изменен до того, как будут прочитаны его значения.
const event = {
target: {
name: 'Name',
value: 123
}
}
function f1(event) {
const { name, value } = event.target;
g(() => { console.info(name, value); });
}
function f2(event) {
g(() => { console.info(event.target.name, event.target.value); });
}
function g(f) {
setTimeout(f, 10);
}
f1(event);
f2(event);
event.target.name = 'New name';
event.target.value = 321;
Пример:
Вы можете добиться одного и того же поведения с деструктуризацией и без нее.
const event = {
target: {
name: 'Name',
value: 123
}
}
function f1(event) {
g(() => {
const { name, value } = event.target;
console.info(name, value);
});
}
function f2(event) {
const name = event.target.name;
const value = event.target.value;
g(() => { console.info(name, value); });
}
function g(f) {
setTimeout(f, 10);
}
f1(event);
f2(event);
event.target.name = 'New name';
event.target.value = 321;
Я понимаю ваш пример. Однако я хочу спросить больше, почему в моем коде появляется ошибка Cannot read properties of null (reading 'name')
, хотя я продолжаю вводить значение во входной тег
Пожалуйста, не задавайте уточняющие вопросы в комментариях. Если у вас есть новый вопрос, опубликуйте новый вопрос.
@ThangThang Дело в том, что если вы получили ответ на свой вопрос, вы можете принять его (для этого есть кнопка) или нет. Если у вас есть дополнительный вопрос, который слишком велик и не помещается в текущий вопрос, просто задайте еще один вопрос.
В первом примере значения
name
иvalue
копируются до вызоваsetFullName
. Во втором примере осуществляется доступ к объектуevent
. Вы получите другое поведение, если объект будет изменен.