Как написать избыточный селектор, который обрабатывает несколько уровней вложенного состояния? - PullRequest
1 голос
/ 05 апреля 2019

Я бы хотел, чтобы мой контейнерный компонент был как можно больше повторного использования. Чтобы добиться этого, я хочу написать повторно используемый селектор, чтобы использовать его в функции mapStateToProps. Я знаю, что эта функция может принимать реквизиты текущего компонента, поэтому я могу передать динамический ключ состояния моему селектору getAllEntities. Проблема возникает, когда я хочу от своего селектора получить первый уровень состояния, а в другом месте - получить некоторое вложенное состояние.

Демонстрация состояния фигуры:

{
  items: { byId: { ... }, allIds: { ... } }
  comparison: {
    otherItems: { byId: { ... }, allIds: { ... } }
    // and so on
  }
}

Демонстрация селектора:

getAllEntities = (state) => state.allIds.map(id => state.byId[id]);

И я использую его в функции mapStateToProps моего компонента:

return { items: getAllEntities(state[ownProps.stateKey]) }

Проблема с моим подходом состоит в том, что (сохраняя возможность многократного использования этого компонента) я могу получить доступ только к первому уровню состояния. Поэтому я не могу передать реквизиты своему компоненту, который поймет, что он должен искать state.comparison.otherItems - посмотрите демонстрацию формы состояния выше.

Я пробовал что-то вроде:

getAllEntities = (state, key1) => {
  if (has(state, key1) {
    return state[key1].allIds.map(id => state[key1].byId[id]);
  }

  return state.allIds.map(id => state.byId[id]);
} 

Так что, если я передам key1 строку - она ​​должна выглядеть глубже в состоянии. Если key1 не передается в реквизит компонента - тогда ведите себя нормально и ищите первый уровень формы состояния.

Я даже не знаю, правильный ли это подход ... Может кто-нибудь помочь мне с этим?

Ответы [ 2 ]

1 голос
/ 05 апреля 2019

Вы можете рекурсивно повторно использовать селектор:

getAllEntities = (state, key1) => {
  if (has(state, key1) {
    return getAllEntities(state[key1])
  }

  return state.allIds.map(id => state.byId[id]);
} 
0 голосов
/ 05 апреля 2019

Спасибо @iofjuupasli, это хорошее решение. Также, как и договорились о Discord Redux Community, просто лучше написать два селектора. Затем, чтобы избежать большого дублирования кода, напишите что-то вроде:

const SomeComponent = () => {};

const WithSomeDataSource = connect(doOneThingHere)(SomeComponent);
const WithAnotherDataSource = connect(doSomethingElseHere)(SomeComponent);
...