я мутирую объект состояния
state = {
selectedHero: { id: "", name: "", saying: "" }
}
с этим методом
handleChangeEvent = e => {
let selectedHero = this.state.selectedHero;
selectedHero[e.target.name] = e.target.value;
this.setState({ selectedHero });
};
я должен написать что-то подобное?
handleChangeEvent = e => {
let selectedHero = { ...this.state.selectedHero };
selectedHero[e.target.name] = e.target.value;
this.setState({ selectedHero });
};
Как говорит AnilRedshift, да, приведенный вами пример синтаксиса распространения будет работать нормально. Для более аккуратного подхода вы также можете написать его одним лайнером, например: this.setState({...this.state.selectedHero, name: e.target.value}). Это одновременно перезапишет значение имени на новом объекте и предотвратит изменение.
@TPHughes - Нет, версия Анила не использует обратный вызов, который необходим. Также name! = [e.target.name]. :-)
Ах да, ты абсолютно прав. Я неправильно прочитал название ключа как просто name. Пишу на телефон: - /. Что вы имеете в виду, зачем нужен обратный вызов?
@TPHughes - См. Мой ответ ниже и ссылку в нем. :-)
@TPHughes - LOL, я не вставил ссылку! Есть сейчас. :-)
Не имел представления! Спасибо очень информативно. :)



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Да, вы изменяете объект selectedHero. Вы должны сделать что-то вроде этого:
handleChangeEvent = e => {
let selectedHero = Object.assign({}, this.state.selectedHero);
selectedHero[e.target.name] = e.target.value;
this.setState({ selectedHero });
};
Вызов Object.assign создаст объект новый, так что исходный объект selectedHero не будет изменен.
Обновлено: ваше отредактированное использование Синтаксис распространения ES2018 тоже работает.
Поскольку это включает в себя настройку состояния на основе существующего состояния (других свойств selectedHero, которые вы копируете), вы должен используете версию обратного вызова setState: reactjs.org/docs/…. объединены / объединены.
И да и нет. Вы не мутируете this.state, но вы мутируете объект, на который ссылается this.state. Этого не следует делать в React.
should I write something like this?
Почти; поскольку это включает в себя обновление состояния на основе состояния (другие свойства selectedHero), вы должен использовать версию обратного вызова setState. Поскольку это означает использование свойств из синтетического события после возврата handleChangeEvent, нам нужно получить их заранее:
handleChangeEvent = e => {
const {name, value } = e.target;
this.setState(prevState => {
let selectedHero = { ...prevState.selectedHero };
selectedHero[name] = value;
return { selectedHero };
})
};
Если вы не используете версию обратного вызова, будет казаться, что большую часть времени что-то работает, и не удастся, когда у вас есть перекрывающиеся обновления состояния для selectedHero (помните, что обновления состояния являются асинхронными); один будет топтать другого.
Если хотите, вы также можете сжать его, используя вычисленное имя свойства после распространения свойства:
handleChangeEvent = e => {
const {name, value} = e.target;
this.setState(prevState => ({selectedHero: {...prevState.selectedHero, [name]: value}}));
};
и даже добавить деструктурирование некоторых параметров:
handleChangeEvent = ({target: {name, value}}) => {
this.setState(prevState => ({selectedHero: {...prevState.selectedHero, [name]: value}}));
};
(Да, деструктуризация произойдет до возврата handleChangeEvent. Это произойдет до того, как ваш явный код в handleChangeEvent вообще запустится.)
Я получаю предупреждение: это синтетическое событие повторно используется по соображениям производительности. Если вы видите это, вы обращаетесь к свойству target в синтетическом событии выпущено / аннулировано. Для него установлено значение null. Если вы должны сохранить исходное синтетическое событие, используйте event.persist ()
@d_oram - Ого, я не знал об этом. Тем не менее, приятное четкое сообщение об ошибке. Придется получить name и value локально, а затем использовать их. Вы, наверное, знаете, как это сделать, но я все равно обновлю ответ.
@d_oram - Готово.
отлично спасибо. Не могли бы вы добавить закрывающую скобку }) после return { selectedHero } в первом примере
@d_oram - Ой! Во втором и третьем также отсутствовал }. :-)
console.info () ..