Выберите взаимозависимые данные в хранилище избыточных данных с помощью повторного выбора createSelector - PullRequest
0 голосов
/ 05 мая 2018

Итак, я использую redux и повторный выбор tool createSelector для запоминания моих селекторов в mapStateToProps, и это здорово.

Теперь у меня есть несколько нормализованных данных в моем магазине и контейнер, который требует взаимозависимых данных из магазина.

Я делаю это, на данный момент, и это работает:

const getItemId = props => parseInt(props.match.params.itemId, 10)

const containerSelector = createSelector(getItemId, itemId =>
  createSelector(
    [getUser, getItem(itemId)],
    (user, item) =>
      createSelector(
        [
          getFoo(item.fooId),
          getBar(item.barId)
        ],
        (foo, bar) => ({ user, item, foo, bar })
      )
  )
)

const mapStateToProps = (state, ownProps) =>
  containerSelector(ownProps)(state)(state)

export default connect(mapStateToProps)(Container)

Вопрос: есть ли лучший способ сделать это?

  1. более читабельно?
  2. Лучшая практика?
  3. Более производительный? (это исполнитель?)

Edit:

Благодаря ответу Тхо Ву я смог сделать его более простым и запоминающимся, например:

import { getUser, getItemById, getFooById } from 'selectors'

// Note: getStuffById are selector factories like: 
//   const getStuffById = id => state => state.stuff.objects[id] 

const itemIdSelector = (_, props) => parseInt(props.match.params.itemId, 10)

const itemSelector = (state, props) => {
   const itemId = itemIdSelector(state, props)
   return getItemById(itemId)(state)
}

const fooSelector = (state, props) => {
   const item = itemSelector(state, props)
   return item ? getFooById(item.fooId)(state) : null
}

const mapStateToProps = createStructuredSelector({ 
  user: getUser, 
  itemId: itemIdSelector, 
  item: itemSelector,
  foo: fooSelector
})

Но я все еще не уверен в этом? А может, это уже хорошо?

1 Ответ

0 голосов
/ 05 мая 2018

Из документации reselect:

Когда селектор подключен к компоненту с подключением, реквизиты компонента передаются в качестве второго аргумента селектору

Так что первый слой createSelector, используемый для получения itemId, на самом деле не нужен, который вы можете заменить на:

const getItem = (state, props) => {
   const itemId = parseInt(props.match.params.itemId, 10)
   return getItem(itemId)
}

Во-вторых, createSelector имеет следующий атрибут:

Селекторы, созданные с помощью createSelector, имеют размер кэша 1. Это означает, что они всегда пересчитывают, когда значение селектора ввода изменяется, так как селектор сохраняет только предыдущее значение каждого входной селектор.

Это означает, что ваш пользовательский селектор будет пересчитываться при каждом изменении user, itemId, item, foo, bar. Трудно сказать об остальных селекторах ввода, но я не вижу никакой связи между user и остальными. Таким образом, вы должны создать отдельный селектор только для user.

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

Что я обычно делаю, так это выравниваю их так:

const getItem = (state, props) => {
   const itemId = parseInt(props.match.params.itemId, 10)
   return getItem(itemId)
}

const userSelector = createSelector(getUser, user => user)
const itemSelector = createSelector(getItem, item => item)

foo и bar более сложны, потому что в вашем коде селекторы ищут изменения в item, item.fooId и foo, которые слишком пересчитываются. Нам по-прежнему нужно вкладывать селекторы, но требуется разделение foo и bar:

const fooFromItemSelector = createSelector(itemSelector, item => getFoo(item.fooId))
const fooSelector = createSelector(fooFromItemSelector, foo => foo)

и то же самое относится к bar.

Наконец, вам нужно сгруппировать их, чтобы создать containerSelector:

import { createStructuredSelector } from 'reselect'

const containerSelector = createStructuredSelector({
    user: userSelector,
    item: itemSelector,
    foo: fooSelector,
    bar: barSelector
})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...