У меня есть объект list
в моем состоянии redux. Он имеет такой набор byId:
{
root: {
id: 'root',
children: ['item_1', 'item_2'],
data: 'Root String',
parent: null,
},
item_1: {
id: 'item_1',
children: ['item_1_1', 'item_1_2', 'item_1_3'],
data: 'Some String',
parent: 'root',
},
item_1_1:
{
id: 'item_1_1'
children: ['item_1_1_1', 'item_1_1_2']
data: 'Some Other string',
parent: 'item_1',
},
item_2: {
...
}
...
}
Теперь я визуализирую приведенный выше список следующим образом:
recursiveRender = (component, idx = 0) => {
const { data, children } = component;
const { list } = this.props;
return (
<div key = {idx}>
{
children.map((child, childIdx) =>
this.recursiveRender(list[child], childIdx))
}
</div>
);
};
render() {
const { list } = this.props;
return this.recursiveRender(list.root);
}
Я хочу обновить порядок дочерних элементов, скажем, item_1
.
В моем действии redux я делаю следующее:
import update from 'immutability-helper';
...
...
return update(state,
{
list: {
[parent]: {
children: {
$splice: [[oldIdx, 1], [idx, 0, id]] },
},
},
}
});
который действительно работает.
Я заметил в React Dev Tools, что все (item_2
и item_3
тоже) рекурсивно визуализированного компонента перекрашивается. Понятия не имею почему. Я удостоверяюсь, что list
неизменяем, но все дерево каждый раз рендерится заново. Как я могу убедиться, что перекрашена только измененная часть (здесь item_1
) list
?
Я не думаю, что использование reselect
является решением здесь, поскольку список является действительно меняется.
Итак, мне нужен динамический mapStateToProps
? Если да, то как не изменить другие элементы списка, зависящие от list
? Или я смотрю не в том месте, и проблема может быть в другом месте приложения.
Функциональные компоненты без сохранения состояния не сравнивают предыдущие и новые свойства. Простым решением было бы использовать вместо этого PureComponent для вашего RecursiveRender
.
О, теперь, когда я проверяю снова, я замечаю, что вы предоставляете объект всего списка для RecursiveRender, что может быть частью проблемы. Вы могли бы написать функцию, которая преобразует ваш объект списка, чтобы вместо использования дочерних элементов в качестве ссылки они были заменены полным объектом, а затем предоставили им рекурсивный список.
Понятно. Да! Я бы попробовал. Но меня беспокоит, что функция «преобразование» каким-то образом будет зависеть от списка и все равно отреагирует на перерисовку. Я пытаюсь понять это.
Что ж, если каждый из потомков является неизменяемым объектом, я думаю, это решит проблему.
children - это неизменяемый массив строк. Я использую immutability-helper
, чтобы убедиться, что каждый объект никогда не мутирует.
О, это не сработало. Потому что у меня в компоненте есть другие реквизиты. Но спасибо!