#javascript #reactjs #react-hooks #state
#javascript #reactjs #реагировать-хуки #состояние
Вопрос:
Проблема
Привет,
Я пытаюсь частично обновить свой объект состояния :
const [elephantProp, setElephantProp] = useState({
name: "",
color: "",
size: "",
race: "",
country: "",
});
Допустим, я хочу обновить только параметры цвета и размера.
Что я пробовал
1
Динамически изменять параметры (в соответствии с входным объектом) :
const handleChange = (input) => {
Object.keys(input).forEach((key) => {
setElephantProp({ ...elephantProp, [key]: input[key] });
};
Вывод: измените только последний параметр (размер).
2
Установите все параметры сразу :
const handleChange = (input) => {
setElephantProp({ ...elephantProp, color: input.color, size: input.size });
};
Вывод: работает, но не является динамическим (если я добавлю параметр к входному объекту, эффектов не будет)
Есть ли у вас какие-либо идеи о том, как динамически обновлять некоторые из моих переменных состояния?
Может быть, мне следует рассмотреть возможность разделения на несколько переменных состояния (неудобно с большим количеством переменных) или использования вложенных объектов?
Комментарии:
1. setElephantProp — это асинхронный метод, вот почему это происходит. Когда вы просматриваете его, вы не получаете обновленное значение состояния. итак, последнее значение обновляется. Не могли бы вы, пожалуйста, попробовать то же самое с циклом синхронизации, а forEach — асинхронный. Надеюсь, это поможет вам.
Ответ №1:
Из вашего кода я собираюсь предположить, что input
это объект, представляющий обновления состояния, например
{
name: "Dumbo",
country: "USA"
}
В этом случае вы можете просто сделать:
const handleChange = (input) => {
setElephantProp({ ...elephantProp, ...input });
}
Как ...input
последнее, его свойства будут перезаписывать elephantProp
свойства, которые имеют тот же ключ.
Пожалуйста, обратите внимание, что таким образом все input
ключи, которых нет в elephantProp
, будут добавлены в состояние; например
const elephantProp = {
name: "",
color: "",
size: "",
race: "",
country: "",
};
const input = {
name: "Dumbo",
country: "USA",
ableToFly: true,
};
const updatedElephantProp = {
...elephantProp,
...input
} // => the updated state will contain the key/value pair 'ableToFly: true' too
console.log(updatedElephantProp)
Такое поведение может быть желательным или нет, в зависимости от ваших потребностей и спецификаций проекта.
Комментарии:
1. Спасибо! Это идеально соответствует моим потребностям, поскольку я контролирую то, что может быть сохранено во входном объекте. Теперь моя функция handleChange выглядит следующим образом: ` const handleChange = (input) => { setElephantProp({ … elephantProp, …ввод }); }; `
Ответ №2:
Вы можете использовать concept useReducer
— обычно предпочтительнее useState, когда у вас сложная логика состояния, которая включает в себя несколько вложенных значений — useReducer
const [changes, onChange] = useReducer((value, change) => ({...(value || {}), ...change}), {});
//used
const {name, color, size, race, country} = changes;
const handleChange = change => {
//example change = {name: 'alex'}
onChange(change);
};
Ответ №3:
React рекомендует использовать несколько состояний для разных переменных. Однако, если вы хотите установить полный объект, вы, скорее всего, предпочтете скопировать объект, и setState
только один раз. Ваш цикл может быть неправильно пойман при повторном отображении, поскольку это асинхронная функция.
Я не уверен, какова ваша реализация, но что-то вроде этого должно работать:
const handleChange = (objectIn) => {
// create a new object merging the old one and your input
const newElephant = {
...elephantProps,
...objectIn
}
setElephantProps(newElephant)
}
Это должно корректно обработать ваш случай. Если вы используете несколько входных данных, я обычно обрабатываю это таким образом:
const onChange = ({ target: { value, name } }) => setElephant({
...elephant,
[name]: value
})
return <input onChange={onChange} name="size" value={elephant.size} />
Ответ №4:
Вы можете передать 2-й параметр в handleChange, например:
const handleChange = (input, name) => {
setElephantProp({ ...elephantProp, [name]: input[name] });
};
Ответ №5:
Одно из ваших решений здесь: codesandbox.io или приведенный ниже код, использующий этот подход.
const onChangeHandaller = (e) => {
setElephantProp({ ...elephantProp, [e.target.name]: e.target.value });
};
const [elephantProp, setElephantProp] = useState({
name: "",
color: "",
size: "",
race: "",
country: ""
});
const onChangeHandaller = (e) => {
setElephantProp({ ...elephantProp, [e.target.name]: e.target.value });
};
return (
<div className="App">
Name:{" "}
<input
value={elephantProp.name}
name="name"
onChange={(e) => onChangeHandaller(e)}
/>{" "}
<br />
Color:{" "}
<input
value={elephantProp.color}
name="color"
onChange={(e) => onChangeHandaller(e)}
/>{" "}
<br />
Size:{" "}
<input
value={elephantProp.size}
name="size"
onChange={(e) => onChangeHandaller(e)}
/>{" "}
<br />
Race:{" "}
<input
value={elephantProp.race}
name="race"
onChange={(e) => onChangeHandaller(e)}
/>{" "}
<br />
Country:{" "}
<input
value={elephantProp.country}
name="country"
onChange={(e) => onChangeHandaller(e)}
/>{" "}
<br />
</div>