Автор оригинала: FreeCodeCamp Community Member.
Дом Кори
Возможно, самая распространенная пункт путаницы в реакции сегодня: государство.
Представьте, что у вас есть форма для редактирования пользователя. Обычно создать один обработчик изменений для обработки изменений на все поля формы. Это может выглядеть что-то подобное:
updateState(event) {
const {name, value} = event.target;
let user = this.state.user; // this is a reference, not a copy...
user[name] = value; // so this mutates state ?
return this.setState({user});
}Концерн находится на линии 4. Строка 4 фактически мутирует состояние, потому что пользовательская переменная является Ссылка указать. Состояние реагирования следует рассматривать как неизменное.
От Реагистрировать документы :
Почему?
- Установка партии работают за кулисами. Это означает, что ручная мутация состояния может быть переопределена при обработке SetState.
- Если вы объявите метод SECCOMPONENTUPDATE, вы не можете использовать проверку внутри, потому что Ссылка на объект не изменится Отказ Таким образом, подход выше имеет потенциальное воздействие на производительность.
Итог : Пример выше часто работает хорошо, но, чтобы избежать краевых чехлов, лечить состояние как неизменного.
Вот четыре способа лечения состояния как неизмеренное:
Подход № 1: Object.Assign
Объект.assign Создает копию объекта. Первый параметр – это цель, то вы указываете один или несколько параметров для свойств, которые вы хотели бы включить. Таким образом, исправление приведенного выше примера включает в себя простое изменение в строку 3:
updateState(event) {
const {name, value} = event.target;
let user = Object.assign({}, this.state.user);
user[name] = value;
return this.setState({user});
}В строке 3 я говорю: «Создайте новый пустой объект и добавьте все свойства на этом .State.user к этому». Это создает отдельную копию пользовательского объекта, который хранится в состоянии. Теперь я в безопасности, чтобы мутировать объект пользователя в строке 4 – это совершенно отдельный объект от объекта в состоянии.
Убедитесь, что Polyfill Object.assign, так как это неподдерживаемый в IE. и не трансформирован Бабел . Четыре варианта для рассмотрения:
Подход № 2: Распространение объекта
Распространение объекта в настоящее время является Этап 3 особенность и может быть транспортирован Бабел . Этот подход более лаконичен:
updateState(event) {
const {name, value} = event.target;
let user = {...this.state.user, [name]: value};
this.setState({user});
}В строке 3 я говорю, «используйте все свойства. Таким образом, этот подход работает аналогично подходу на объект. Назначение, но имеет два преимущества:
- Ни один полифилл не требуется, Так как Бабел может транпиливать
- Более краткий
Вы можете даже использовать разрушительную и настраивать, чтобы сделать это одноклассник:
updateState({target}) {
this.setState({user: {...this.state.user, [target.name]: target.value}});
}Я изуродован событие в подписи метода, чтобы получить ссылку на Event.target. Затем я объявляю, что государство должно быть установлено на копию этого .state.user с соответствующим свойством, установленным на новое значение. Мне нравится, насколько это зависит. В настоящее время это мой любимый подход к написанию обработчиков изменения. ?
Эти два подхода выше являются наиболее распространенными и простыми способами обрабатывания неизменного состояния. Хотите больше энергии? Проверьте два других варианта ниже.
Подход № 3: хелпер неизменности
Несмотря на молчание это удобная библиотека для мутации копии данных без изменения источника. Эта библиотека предложена в Реагические документы Отказ
// Import at the top:
import update from 'immutability-helper';
updateState({target}) {
let user = update(this.state.user, {$merge: {[target.name]: target.value}});
this.setState({user});
}На строке 5 я звоню слиянием, что это Один из многих команд предоставляется иммутабельностью-помощником. Многое нравится Object.Ascign, я передаю его целевой объект в качестве первого параметра, то укажите свойство, которое я хотел бы объединить.
Там гораздо больше для негодования, чем это. Он использует синтаксис, вдохновленный языком запроса MongoDB и предлагает Разнообразие мощных способов работы с неизменными данными Отказ
Подход № 4: Immuteable.js
Хотите программически соблюдать неизменность? Рассмотрим Immutable.js Отказ Эта библиотека предоставляет неизменные структуры данных.
Вот пример, используя неизменяемую карту:
// At top, import immutable
import { Map } from 'immutable';
// Later, in constructor...
this.state = {
// Create an immutable map in state using immutable.js
user: Map({ firstName: 'Cory', lastName: 'House'})
};
updateState({target}) {
// this line returns a new user object assuming an immutable map is stored in state.
let user = this.state.user.set(target.name, target.value);
this.setState({user});
}Существует три основных шага выше:
- Импорт неизменен.
- Установите состояние на неизменной карте в конструкторе
- Используйте метод SET в обработчике Изменения, чтобы создать новую копию пользователя.
Красота Immutable.js: Если вы попытаетесь использовать состояние штата напрямую, он не будет потерпеть неудачу Отказ С другими подходами выше, легко забыть, и отреагируйте, не предупреждают вас, когда вы напрямую мутатет.
Нисходящие неизменные?
- Раздувать Отказ Immuteable.js добавляет 57 тыс. Долларов до вашего пакета. Учитывая библиотеки, такие как Preact может заменить реагирование только в 3K Трудно принять.
- Синтаксис Отказ Вы должны ссылаться на объектные свойства с помощью строк и вызовов метода, а не напрямую. Я предпочитаю User.name over user.get («Имя»).
- Yattl (Еще одна вещь, чтобы узнать) – Любой, кто присоединяется к вашей команде, должен узнать еще один API для получения и установки данных, а также новый набор данных DataTypes.
Пара других интересных альтернатив для рассмотрения:
Предупреждение: следите за вложенными объектами!
Вариант № 1 и № 2 выше (Object.Assign и Object Spread) Только сделать неглубокий клон. Так что, если ваш объект содержит вложенные объекты, Эти вложенные объекты будут скопированы посредством ссылки вместо по стоимости . Поэтому, если вы измените вложенный объект, вы мутируете оригинальный объект. ?
Будь хирургическим о том, что вы клонируете. Не закрывайте все вещи. Клонировать объекты, которые изменились. Хельпер неизменности (упомянутый выше) делает это легко. Как и альтернативы, как потрясающий , upteep или Долгий список альтернатив .
Вы можете быть соблазнены достичь глубоких инструментов слияния, таких как Глубокий клон или lodash.merge , но Избегайте слепого глубокого клонирования Отказ
Вот почему:
- Глубоко клонирование дорого.
- Глубоко клонирование, как правило, расточительно (вместо этого только клонируется, что на самом деле изменилось)
- Глубокие клонирование вызывает ненужные рендеры, поскольку реагирование считает, что все изменилось, когда на самом деле изменилось только определенный дочерний объект.
Благодаря Дэну Абрамову за предложения, которые я упомянул выше:
Я не думаю, что CLONDEEP () – хорошая рекомендация. Это может быть очень дорого. Только копируйте детали, которые фактически изменились. Библиотеки, такие как Immutability-Helper ( https://t.co/yadmmpioo8 ), updeep ( https://t.co/p0mzd19hcd ) или Immer ( https://t.co/Vyra6cd4ip ) Помогите с этим.
Последний совет: рассмотрите возможность использования функционального SetState
Еще одна морщина может укусить вас:
Поскольку STATSTATE CONSTS BATCHED, код, как это приводит к ошибке:
updateState({target}) {
this.setState({user: {...this.state.user, [target.name]: target.value}});
doSomething(this.state.user) // Uh oh, setState merely schedules a state change, so this.state.user may still have old value
}Если вы хотите запустить код после завершения вызова SetState, используйте форму обратного вызова STETSTATE:
updateState({target}) {
this.setState((prevState) => {
const updatedUser = {...prevState.user, [target.name]: target.value}; // use previous value in state to build new state...
return { user: updatedUser }; // And what I return here will be set as the new state
}, () => this.doSomething(this.state.user); // Now I can safely utilize the new state I've created to call other funcs...
);
}Мой взять
Я восхищаюсь простотой и легким весом опции № 2 выше: распространение объекта. Он не требует полифиллирования или отдельной библиотеки, я могу объявить обработчик изменений на одной строке, и я могу быть хирургическим о том, что изменилось. ? Работа со вложенными объектами структур? В настоящее время я предпочитаю Потрясающий
Есть другие способы, которыми вы любите обращаться с государством в реакции? Пожалуйста, звоните через комментарии!
Ищете больше на реагировании? ⚛
Я был авторизован несколько курсов React и JavaScript На плютаре ( бесплатная пробная версия ). Мой последний, ” Создание многоразовых реагированных компонентов «Только что опубликовал!?
Дом Кори автор Несколько курсов по JavaScript, React, Clear Code, .NET и многое другое на Pluralsight Отказ Он главный консультант по адресу Reactjsconsulting.com , архитектор программного обеспечения в Vinsolutions, Microsoft MVP и поезда разработчиков программного обеспечения на международном уровне по методике программного обеспечения, такими как интерфейс разработки и чистого кодирования. Твиты CORY о JavaScript и Front-End Development в Twitter, как @houseCor Отказ
Оригинал: “https://www.freecodecamp.org/news/handling-state-in-react-four-immutable-approaches-to-consider-d1f5c00249d5/”