В списке меняется один элемент, происходит рендер все остальных(Immutable + memoize)
Полностью готовый пример https://stackblitz.com/edit/react-lyx4ka?file=redux%2Freducers%2Flist.js
Есть массив(OrderedMap из ImmutableJS), который содержит объект с такими данными { id: 1, isActive: false, text: ‘item-1’ }. Список мы храним в store(redux) По нажатию на элемент, мы меняем значение поля isActive с false => true. В компонент List передую имутабельную структуру OrderedMap, после с помощью функции lodash/memoize запоминаю объект:
function normalizeList(list) { return list.valueSeq().toArray(); } const memoizeList = memoize(normalizeList); const handleSelectedItem = (id) => updateData(id);
Элементы списка это Item(компоненты)
Происходит перерендер всех элементов после нажатия на один из них, хотя если все поля без изменений это не новый объект(ссылка на него).
Как раз на днях хотел понять в чём разница Redux и Mobx изнутри. Нашлась вот такая статья.
Читая чат русскоязычного react сообщества в телеграмме ( https://t.me/react_js ), я вижу как с постоянной регулярностью появляются обсуждения mobx-а, сравнения с redux-ом с аргументациями про магию,...
И там рассматривался похожий пример.
Первый недостаток — это то, что мы не можем теперь просто взять и обновить любое свойство объекта данных в приложении. Из-за требования возвращать каждый раз новый иммутабельный объект целого состояния, нам нужно вернуть новый объект и также пересоздать все родительские объекты и массивы. Например, если объект состояния хранит массив проектов, каждый проект хранит массив задач, и каждая задача хранит массив комментариев:
То для того чтобы обновить текст у объекта комментария мы не можем просто выполнить comment.text = 'new text'
— нам нужно выполнить сначала пересоздание объекта комментария ( comment = {...comment, text: 'updated text'}
), дальше нужно пересоздать объект задачи и скопировать у туда ссылки на другие комментарии ( task = {...task, tasks: [...task.comments]}
), дальше пересоздать объект проекта и скопировать туда ссылки на другие задачи ( project = {...project, tasks: [...project.tasks]}
) и в конце уже пересоздать объект состояние и также скопировать ссылки на другие проекты ( AppStat = {...AppState, projects: [...AppState.projects]}
).
То есть, проблема в самой иммутабельности. И то что соседние элементы списка остались неизменными — это ничего не значит. Вся цепочка родителей пересоздаётся
2 лайка
В редьюсере пересоздается весь List. Во-первых, state.setIn(['list'])
создает новый list, во вторых вот тут:
if (action.id === item.id) {
const newItem = new ListItemRecord(item).set('isActive', true)
return newItem;
}
const newA = new ListItemRecord(item).set('isActive', false)
return newA
Ты пересоздаешь каждый элемент списка.
Можно, конечно, заморочиться и поковырять редьюсер, мемоизы и вот это вот все, а можно просто прикрутить shouldComponentUpdate
в ListItem
.
2 лайка
Johnny
13.Июль.2019 17:59:03
4
Quote Происходит перерендер всех элементов после нажатия на один из них, хотя если все поля без изменений это не новый объект(ссылка на него). Unquote
Ну ведь у нас Shallow Diffing в реакте.