React / Redux: эффективно изменить соответствующее состояние компонента в дереве Redux - PullRequest
0 голосов
/ 05 февраля 2020

Таким образом, у меня, по сути, есть похожая иерархия между моими компонентами и состоянием Redux, представленная ниже, где каждый компонент имеет id, name, details, et c:

Redux hierarchy:
parent -> child1 -> element1
                    element2
                    element3
          child2 -> element1
                    element2

React hierarchy:
ParentComponent -> ChildComponent -> ElementComponent

Предположим, я хотел, чтобы element2 child1 изменил свое имя, когда оно отражается в состоянии Redux, как бы я go сделал это эффективно?

Что я хочу, так это каким-то образом создать ссылку, используя id элемента element2 child1 и id в состоянии, поэтому я могу изменить соответствующее состояние Redux без глубокого поиска в хранилище Redux, чтобы изменить соответствующее состояние.

Я мог бы эффективно создать это с использованием модели состояния React, и каждый компонент управляет своим собственным состоянием, но, поскольку мне нужно это состояние в другом месте, как бы я справился с этим в состоянии Redux? Заранее спасибо.

1 Ответ

0 голосов
/ 15 февраля 2020

Обычно вы можете просто go спускаться по предсказанному пути объекта, но поскольку путь объекта может быть переменным из-за природы element s, я решил использовать комбинацию грубой силы и предсказанного пути объекта.

В этом конкретном сценарии Parent является общим узлом между всеми element с, поэтому поиск грубой силы для id будет работать достаточно хорошо.

Эта функция многократного использования обеспечит грубую силу рекурсивный поиск в узле root для каждого объекта и предоставление обратного вызова для выполнения каждого объекта.

export const iterateNodes = (obj, callback) => {
    if (!obj) return undefined

    for (let property in obj) {
        if (obj.hasOwnProperty(property) && obj[property] != null) {
            if (obj[property].constructor === Object) {
                iterateNodes(obj[property], callback)
                callback(obj[property])
            } else if (obj[property].constructor === Array) {
                for (let i = 0; i < obj[property].length; i++) {
                    iterateNodes(obj[property][i], callback)
                    callback(obj[property][i])
                }
            } else {
                // console.log(obj[property])
            }
        }
    }
    return obj
}

Это было извлечено из другого вопроса StackOverflow и немного изменено. Кажется, я не могу найти источник.

Затем вы можете создать другую функцию для изменения узла с определенными параметрами. Этот фрагмент имеет опции overwrite на случай необходимости перезаписи всего объекта.

export const modifyNodeById = (
    root,
    id,
    modification,
    options = {}
) => {
    if (!id) throw new Error('id not specified')

    return iterateNodes(root, node => {
        if (node.id === id) {
            if (options.overwrite)
                Object.getOwnPropertyNames(node).forEach(key => delete node[key])
            Object.assign(node, { ...modification })
        }
    })
}

Примечание о импорте: эта функция изменяет объект.

Состояние должно изменяться избегать на 100%, поэтому самый простой выход - использовать функцию loda sh cloneDeep для создания глубокой копии. Вы, вероятно, могли бы оптимизировать копирование только необходимых ветвей в штате, но если ваше состояние не равно cc, оно, вероятно, не стоит.

Таким образом, окончательный ответ может быть:

modifyNodeById(parent, 13, { isUnlocked: true })

Чтобы добавить свойства к узлу объекта с помощью id: 13, начните поиск в parent.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...