Разработка эффективного редюсера для большого состояния с редуксом

Я использую редукцию с реакцией и машинописью для своего приложения. Я работаю со многими элементами, используемыми в разных местах моего приложения. Мое состояние выглядит так:

{
    items: {42: {}, 53: {}, ... }, //A large dictionary of items
    itemPage1: {
        items: [42, 34, 67, ...],
        ...
    },
    itemPage2: { ... 
    },
    ...
}

Я хочу написать эффективный редьюсер элементов, но элементы большие, и я не могу каждый раз создавать глубокие копии. Судя по gaearon, мне это не нужно (извлечено из здесь): Redux не требует глубокого клонирования состояния при каждом действии. Он просто просит вас вернуть новые объекты для частей, которые изменились. Вы можете повторно использовать предыдущее состояние для любых частей дерева, которые не изменились. .

Это замечательно! Однако я новичок во всем этом, и я не уверен, как правильно реализовать редуктор. То, что у меня есть до сих пор внутри моего редуктора, это:

case UPDATE_ITEM_LABEL:
    return (<any>Object).assign({}, state, {
          item_id: (<any>Object).assign({}, state[action.item_id], {
              label: action.value
          })
    })

Таким образом, он копирует все элементы старого состояния в новый объект, а затем объединяет результат с измененным объектом с новым обновленным значением. Я надеюсь, что элементы во время первого assign передаются по ссылке и поэтому не копируются глубоко? Если это так, то все в порядке, так как я могу позволить себе глубоко скопировать один элемент и несколько простых ссылок для каждого действия. Также я обнаружил, что можно использовать immutable.js для решения этой проблемы, если метод, который я предлагаю, работает, зачем людям использовать immutable.js?


person user3091275    schedule 31.07.2016    source источник
comment
Immutable пытается эффективно использовать существующие данные. Цель состоит в том, чтобы избежать необходимости принимать подобные решения самостоятельно.   -  person Dave Newton    schedule 31.07.2016


Ответы (1)


Я сделал быстрый тест, чтобы убедиться, что мой метод работает:

var item1 = {prop1: 'item1', prop2: 'haha'};
var item2 = {prop1: 'item2', prop2: 'hehe'};
var items = {1:item1, 2:item2};

console.log(items);

Этот дисплей, как и ожидалось:

[object Object] {
  1: [object Object] {
    prop1: "item1",
    prop2: "haha"
  },
  2: [object Object] {
    prop1: "item2",
    prop2: "hehe"
  }
}

Теперь мы используем assign для получения следующего состояния, изменяя один из ключей для item2:

var items = Object.assign({},items, { 2: Object.assign({}, items[2],
    {
        prop2: 'huhu' 
    })
});

console.log(items);

Этот дисплей, как и ожидалось:

[object Object] {
  1: [object Object] {
    prop1: "item1",
    prop2: "haha"
  },
  2: [object Object] {
    prop1: "item2",
    prop2: "huhu"
  }
}

Теперь самое интересное, если мы используем начальную ссылку на item1 и item2 для изменения свойств prop1:

item1.prop1 = 'ITEM1'
item2.prop1 = 'ITEM2'

console.log(items);

Мы обнаруживаем, что только item2 был глубоко скопирован, а это поведение, которое я хочу:

[object Object] {
  1: [object Object] {
    prop1: "ITEM1",
    prop2: "haha"
 },
  2: [object Object] {
    prop1: "item2",
    prop2: "huhu"
  }
}
person user3091275    schedule 31.07.2016
comment
Вы должны разбить это на отдельные редукторы и использовать combineReducers - person Mulan; 03.08.2016