使用React Redux mapStateToProps的可重用组件

时间:2017-07-12 19:04:22

标签: reactjs redux react-redux

React 组件OilBarrel连接了我的 redux 商店以创建容器OilBarrelContainer

// ---- component

class OilBarrel extends Component {
  render() {
     let data = this.props.data;
     ...
  }
}

// ---- container

function mapStateToProps(state) {
  let data = state.oilbarrel.data;
  ...
}

const OilBarrelContainer = connect(mapStateToProps)(OilBarrel)

// ---- reducer

const oilbarrel = (state = {}, action) => {
  let data = state.data;
}

const storeFactory = (server = false, initialState = {}) => {
    return applyMiddleware(...middleware(server))(createStore)(
        combineReducers({oilbarrel, otherReducer1, otherReducer2}),
        initialState
    )
}

我觉得很奇怪mapStateToProps()收到顶级状态对象(应用程序的整个状态),要求我遍历state.oilbarrel.data,当reducer(方便地)只接收到分支时属于此组件的状态。

这限制了重用此容器的能力,而不知道它在何处适合状态层次结构。我做错了我的mapStateToProps()正在接收完整状态吗?

3 个答案:

答案 0 :(得分:2)

这不是故意的,因为您可能希望在组件中使用状态的其他部分。一个选项是将选择器(mapStateToProps)保存在与组件不同的文件中,这将有助于您重用选择器,如果您的应用程序非常庞大且复杂,您还可以检出诸如重新选择之类的库,这有助于提高选择器的效率

答案 1 :(得分:2)

这是mapStateToProps行为。您必须将redux状态视为单一的事实来源(顺便说一句,就是它的真实情况),而与项目中的组件无关。没有出路,您必须知道状态中特定数据的确切层次结构,以将其传递给容器组件。

答案 2 :(得分:2)

Dan Abramov在Colocating Selectors with Reducers下的高级redux课程中为此提供了解决方案。

这个想法是,对于每个reducer,都有一个选择器,而选择器只知道它的reducer结构。更高级别减速器的选择器,包含较低级别的减速器,以及它们的一部分状态,等等。

该示例取自课程github

在todos reducer文件中:

export const getVisibleTodos = (state, filter) => {
  switch (filter) {
    case 'all':
      return state;
    case 'completed':
      return state.filter(t => t.completed);
    case 'active':
      return state.filter(t => !t.completed);
    default:
      throw new Error(`Unknown filter: ${filter}.`);
  }
};

在主reducer文件中:

export const getVisibleTodos = (state, filter) =>
  fromTodos.getVisibleTodos(state.todos, filter);

现在你可以在不知道结构的情况下获得你所在州的每个部分。但是,它增加了很多样板。