首页 文章

React Redux - 我可以让mapStateToProps只占用部分状态吗?

提问于
浏览
11

我想制作可以插入任何react-redux应用程序的可重用模块 . 理想情况下,我的模块在顶层有一个容器组件,操作和reducer(然后是容器下面的任何表示组件) . 我希望模块只能处理自己应用程序状态的一部分,理想情况下不必了解应用程序状态的其余部分(因此它是真正的模块化) .

Reducers只能在部分状态下工作(使用combineReducers),所以我很高兴 . 但是,对于容器组件,mapStateToProps似乎总是处于应用程序的完整状态 .

如果mapStateToProps只接受我在模块中处理的相同“状态切片”(就像reducer一样),我会喜欢它 . 这样我的模块就会真正模块化 . 这可能吗?我想我可以把状态的那一部分传递给这个组件的道具(所以我可以使用mapStateToProps的第二个参数,ownProps),但我不确定这是否具有相同的效果 .

6 回答

  • 0

    这实际上是一个复杂的话题 . 因为Redux是一个单一的全局存储,所以完全封装,完全可重用的即插即用逻辑集的想法确实变得相当困难 . 特别是,虽然reducer逻辑可以相当通用并且不知道它在哪里,但是选择器函数需要知道树中的哪个位置才能找到该数据 .

    你问题的具体答案是“不, mapState 总是给出完整的状态树” .

    我确实有许多相关资源的链接,这可能对您的情况有所帮助:

  • -1

    如你所知,Redux只有一个商店,所以它知道要做的就是将整个商店传递给你的mapStateToProps函数 . 但是,使用对象解构,您可以指定所需的存储中的哪些属性,而忽略其余属性 . 像'function mapStateToProps({prop1,prop2})'这样的东西只能捕获商店中的那两个属性而忽略其余的属性 . 您的功能仍在接收整个商店,但您只是指出这些道具只对您感兴趣 .

    在我的例子中,'prop1'和'prop2'将是你在'combineReducers'调用期间为reducers指定的名称 .

  • 0

    理想情况下,它的工作方式是获取状态,然后使用解构器从中提取值 . redux适用于单一状态的概念

    例如:-

    function mapStateToProps(state){
        const { auth } = state  //just taking a auth as example.
        return{
          auth
        }
    }
    
  • 0

    我遇到了同样的问题,因为正如你所说,redux / react-redux的当前实现允许在状态上拆分reducers,但mapDispatchToProps总是传递整个状态树 .

    https://stackoverflow.com/a/39757853/444794不是我想要的,因为这意味着我们必须在使用我们模块的每个react-redux应用程序中复制所有选择器逻辑 .

    我目前的解决方法是将状态切片作为支柱传递下去 . 这遵循一种组成模式,但同时消除了直接进入国家的清洁,我对此感到失望 .

    例:

    通常,您想要这样做:

    const mapStateToProps = (state) => {
      return {
        items: mySelector(state)
      }
    }
    
    const mapDispatchToProps = (dispatch) => {
      return {
        doStuff: (item) => {
          dispatch(doStuff(item))
        }
      }
    }
    
    class ModularComponent extends React.Component {
      render() {
        return (
          <div>
            { this.props.items.map((item) => {
              <h1 onclick={ () => this.props.doStuff(item) }>{item.title}</h1>
            })}
          </div>
        )
      }
    }
    
    export default connect(mapStateToProps, mapDispatchToProps)(ModularComponent)
    

    但由于此模块包含在一个应用程序中,其中状态现在是几个事物(即键值)而不是项目列表,这将不起作用 . 我的解决方法看起来像:

    const mapStateToProps = (_, ownProps) => {
      return {
        items: mySelector(ownProps.items)
      }
    }
    
    const mapDispatchToProps = (dispatch) => {
      return {
        doStuff: (item) => {
          dispatch(doStuff(item))
        }
      }
    }
    
    class ModularComponent extends React.Component {
      render() {
        return (
          <div>
            { this.props.items.map((item) => {
              <h1 onclick={ () => this.props.doStuff(item) }>{item.title}</h1>
            })}
          </div>
        )
      }
    }
    
    export default connect(mapStateToProps, mapDispatchToProps)(ModularComponent)
    

    使用该模块的应用程序如下所示:

    const mapStateToProps = (state) => {
      return {
        items: state.items
        stuffForAnotherModule: state.otherStuff
      }
    }
    
    class Application extends React.Component {
      render() {
        return (
          <div>
            <ModularComponent items={ this.props.items } />
            <OtherComponent stuff={ this.props.stuffForAnotherModule } />
          </div>
        )
      }
    }
    
    export default connect(mapStateToProps)(Application)
    
  • 9

    虽然 mapStateToProps (您传递给连接的第一个函数)按照您的说法传递给整个商店,但它的工作是将状态的特定部分映射到组件 . 因此,只有从mapStateToProps返回的内容才会被映射为组件的prop .

    所以,让我们说你的州看起来像这样:

    {
        account: {
            username: "Jane Doe",
            email: "janedoe@somemail.com",
            password: "12345",
            ....
        },
        someOtherStuff: {
            foo: 'bar',
            foo2: 'bar2'
        },
        yetMoreStuff: {
            usuless: true,
            notNeeded: true
        }
    }
    

    并且您的组件需要来自 accountfoo 的所有内容,然后您的 mapStateToProps 将如下所示:

    const mapStateToProps = ({ account, someOtherStuff }) => ({
        account,
        foo: { someOtherStuff }
    });
    export default connect(mapStateToProps)(ComponentName)
    

    然后你的组件将从你的redux映射prop accountfoo 州 .

  • 1

    你的问题的答案是肯定的 . 给出的答案都涵盖同一事物的不同方面 . 首先,Redux创建了一个包含多个reducer的商店 . 所以你会想要将它们组合起来:

    export default combineReducers({
      people: peopleReducer,
      departments: departmentsReducer,
      auth: authenticationReducer
    });
    

    然后,假设您有一个DepartmentsList组件,您可能只需要将 departments 从商店映射到您的组件(也可能是映射到props的一些操作):

    function mapStateToProps(state) {
      return { departments: state.departments.departmentsList };
    }
    
    export default connect(mapStateToProps, { fetchDepartments: fetchDepartments })(DepartmentsListComponent);
    

    然后在组件内部基本上是:

    this.props.departments
    this.props.fetchDepartments()
    

相关问题