【问题标题】:How can I get ownProps using reselect on redux?如何在 redux 上使用 reselect 获得 ownProps?
【发布时间】:2016-04-03 22:31:17
【问题描述】:

我想根据mapStateToProps 的一些ownProps 使用重新选择创建一个带有记忆功能的选择器。

【问题讨论】:

    标签: reactjs redux reselect


    【解决方案1】:

    您可以通过使用react-redux 提供的connect 方法将选择器连接到组件,然后将组件道具(ownProps)作为第二个参数传递给选择器。

    container.js

    import { connect } from 'react-redux';
    import { getVisibleTodos } from './selectors';
    
    ...
    
    const mapStateToProps = (state, props) => {
      return {
        todos: getVisibleTodos(state, props),
      };
    };
    
    const VisibleTodoList = connect(
      mapStateToProps,
    )(TodoList);
    
    export default VisibleTodoList;
    

    然后您可以在选择器中访问这些道具

    selectors.js

    import { createSelector } from 'reselect';
    
    const getVisibilityFilter = (state, props) =>
      state.todoLists[props.listId].visibilityFilter;
    
    const getTodos = (state, props) =>
      state.todoLists[props.listId].todos;
    
    const getVisibleTodos = createSelector(
      ...
    );
    
    export default getVisibleTodos;
    

    但是,如果您有多个要从中传递道具的组件实例,这将不会正确记忆。在这种情况下,选择器每次都会收到不同的 props 参数,因此它总是会重新计算而不是返回缓存值。

    要在多个组件之间共享一个选择器,同时传递道具保留记忆,组件的每个实例都需要它自己的选择器私有副本。

    您可以通过创建一个函数来实现此目的,该函数每次调用时都会返回一个新的选择器副本。

    selectors.js

    import { createSelector } from 'reselect';
    
    const getVisibilityFilter = (state, props) =>
      state.todoLists[props.listId].visibilityFilter;
    
    const getTodos = (state, props) =>
      state.todoLists[props.listId].todos;
    
    const makeGetVisibleTodos = () => {
      return createSelector(
        ...
      );
    }
    
    export default makeGetVisibleTodos;
    

    如果提供给 connect 的 mapStateToProps 参数返回一个函数而不是一个对象,它将用于为容器的每个实例创建一个单独的 mapStateToProps 函数。

    考虑到这一点,您可以创建一个函数 makeMapStateToProps,它会创建一个新的 getVisibleTodos 选择器,并返回一个对新选择器具有独占访问权限的 mapStateToProps 函数:

    import { connect } from 'react-redux';
    import { makeGetVisibleTodos } from './selectors';
    
    ...
    
    const makeMapStateToProps = () => {
      const getVisibleTodos = makeGetVisibleTodos();
      const mapStateToProps = (state, props) => {
        return {
          todos: getVisibleTodos(state, props),
        };
      };
      return mapStateToProps;
    };
    
    const VisibleTodoList = connect(
      makeMapStateToProps,
    )(TodoList);
    
    export default VisibleTodoList;
    

    现在VisibleTodosList 容器的每个实例都将获得自己的mapStateToProps 函数和私有getVisibleTodos 选择器。无论容器的渲染顺序如何,记忆现在都可以正常工作。


    这是改编自Reselect documentation

    【讨论】:

    • 嗨,我有一个关于这个的问题:如果我想为 makeGetVisibleTodos() 添加参数怎么办?假设我有两个组件使用相同的参数化选择器,但它们的 props 命名不同,在这种情况下,这将不起作用,因为底层 getTodosgetVisibilityFilter 将失败。示例:betterFoobar = (id) => createSelector(foobarSelector, (foobarValue)=>id+foobarValue) 到目前为止我的想法:mapStateToProps = createStructuredSelector({ enhancedFooBar : (state, ownProps) => betterFoobar(ownProps.id)(state,ownProps)}) 但我想这不会记住。
    • 为了更清楚地说明我的观点,我提出这个问题是因为在选择器中依赖 ownProps 将 React 组件 API 与 Redux 状态选择器紧密耦合。这使得选择器不能跨组件重用,而它们是一个非常强大的重用工具。例如,我想在电子的主进程和渲染器进程以及多个组件中使用我的选择器。在这种情况下,接受的解决方案似乎不适合(当然它回答了最初的问题,它可能只需要一些更改就可以在我的用例中工作)。
    猜你喜欢
    • 1970-01-01
    • 2019-11-13
    • 1970-01-01
    • 2016-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-20
    相关资源
    最近更新 更多