Каков наилучший способ получить данные из API в контейнер Redux с помощью Reselect в ReactJS?

Я знаю, что этот вопрос может показаться дублированным, но я не нашел хорошего решения по этому вопросу, особенно в сочетании с reselect< /а>.

Пожалуйста, рассмотрите следующий компонент контейнера redux:

export default connect((state, props) => {
  return {
    ...props
  }
}, (dispatch) => {
  if (shouldLoadClinic(store.getState())) {
    dispatch(loadClinicInfo())
  }

  if (shouldLoadTimezones(store.getState())) {
    dispatch(loadTimezones())
  }

  return {}
})(SettingsClinic)

Где например. shouldLoadClinic() определяется следующим образом:

import { createSelector } from 'reselect'

export const isClinicLoaded = ({ clinic }) => {
  return clinic.current !== null
}

export const isClinicLoading = ({ clinic }) => {
  return clinic.pending
}

export const shouldLoadClinic = createSelector([
  isClinicLoaded,
  isClinicLoading
], (isLoaded, isLoading) => {
  return !isLoaded && !isLoading
})

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

  1. getState() требуется из внешней области (было бы неплохо, чтобы реквизит getState передавался вместе с аргументом «отправка»).

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

  3. Условия - может быть, вызов метода "shouldLoadTimezonesIfNeeded()" для замены условия был бы более чистым способом?

У тебя есть идеи? Может быть, просто ссылок с референсами будет достаточно.

Заранее спасибо.


person user1356619    schedule 03.01.2018    source источник


Ответы (1)


  1. Вы можете использовать 3-й аргумент connect (mergedProps), чтобы иметь доступ к stateProps и dispatchProps, таким образом, используйте selectors внутри mapStateToProps, а затем используйте результат в mergedProps - то же самое для dispatch. Другой способ сделать это — использовать промежуточное ПО redux-thunk, таким образом, вы можете просто отправлять действия для загрузки каждый раз и проверять наличие ifNeeded в файле thunk.
  2. Зачем издеваться над всем? вам просто нужно смоделировать начальное состояние хранилища и ответы на любые запросы API.
  3. Именование выглядит хорошо для меня.

p.s. Мне не очень нравится патч с обезьянами, который вы делаете в mapDispatchToProps. Вам лучше всегда возвращать функцию для загрузки данных и вызывать ее внутри вашего компонента componentDidMount или позаботиться о загрузке всех данных вместе в HOC.

Я имею в виду изменить это:

if (shouldLoadClinic(store.getState())) {
  dispatch(loadClinicInfo())
}
if (shouldLoadTimezones(store.getState())) {
  dispatch(loadTimezones())
}
return {}

Во что-то вроде этого:

return {
  loadData: () => {
    dispatch(loadClinicInfo());
    dispatch(loadTimezones());
  }
}

Последнее замечание: здесь — небольшой пример HOC, который я создал, чтобы позаботиться о загрузке data и показывать загрузчик при этом. Надеюсь, поможет.

Вот пример третьего аргумента connect mergedProps:

const mapStateToProps = state => ({someData: selectSomeData(state)});
const mapDispatchToProps = dispatch => ({dispatch})
const mergedProps = (stateProps, dispatchProps) => {
  return {
    loadData: () => stateProps.someData
      ? dispatchProps.loadData()
      : null
  }
}
connect(mapStateToProps, mapDispatchToProps, mergedProps)(Component)
person Johnny Klironomos    schedule 04.01.2018
comment
1) Не могли бы вы показать мне пример третьего аргумента, о котором вы говорите? Это поможет. - person user1356619; 04.01.2018
comment
1 - b) Мне не нравится делать условия в действиях, главным образом потому, что условие должно быть в селекторах, которые нельзя использовать в действии (рекурсия) 2) вы правы в этом 3) я думаю, что моя точка зрения была на самом деле другой... обернуть условие в метод и заменить его - person user1356619; 04.01.2018
comment
@user1356619 user1356619 Я обновил свой ответ, включив (в конце) пример аргумента mergedProps. - person Johnny Klironomos; 05.01.2018