在ReactJS中使用Reselect从api获取数据到Redux容器的最佳方法是什么?

时间:2018-01-03 22:10:10

标签: reactjs redux react-redux reselect

我知道这个问题可能听起来重复,但我没有找到任何好的解决方案,特别是与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 prop与“dispatch”arg一起传递会很高兴。)

  2. 难以测试 - 为了测试数据是否在mount上加载我将不得不模拟存储,选择器和操作。

  3. 条件 - 也许调用方法“shouldLoadTimezonesIfNeeded()”来替换条件会更干净吗?
  4. 你有什么想法吗?也许只是与参考文献的链接就足够了。

    提前致谢。

1 个答案:

答案 0 :(得分:0)

  1. 您可以使用connectmergedProps)的第3个参数来访问stateProps和dispatchProps,这样就可以使用selectors内的mapStateToProps然后使用结果在mergedProps中 - dispatch相同。另一种方法是使用redux-thunk中间件,这样,您可以随时调度要加载的操作,并在ifNeeded中检查thunk
  2. 为什么要嘲笑一切?你只需要模拟商店的初始状态和任何api请求的响应。
  3. Naming看起来很好。
  4. p.s:我真的不喜欢你在mapDispatchToProps做的猴子补丁。最好总是返回一个加载数据的函数,并在组件的componentDidMount内调用它,或者在HOC中一起加载数据。

    我的意思是改变这个:

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

    这样的事情:

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

    最后的注释,here是我创建的HOC的一个小小的要点,用于处理数据并在执行时显示加载程序。希望它有所帮助。

    以下是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)