В списке меняется один элемент, происходит рендер все остальных(Immutable + memoize) ReactJS

В списке меняется один элемент, происходит рендер все остальных(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 изнутри. Нашлась вот такая статья.

И там рассматривался похожий пример.

То есть, проблема в самой иммутабельности. И то что соседние элементы списка остались неизменными — это ничего не значит. Вся цепочка родителей пересоздаётся

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 лайка

Quote Происходит перерендер всех элементов после нажатия на один из них, хотя если все поля без изменений это не новый объект(ссылка на него). Unquote

Ну ведь у нас Shallow Diffing в реакте.