Redux,如果我想访问数据,是否必须在我的所有容器中导入商店?

jam*_*non 52 reactjs redux

也许我并没有围绕redux,但我见过的所有例子都没有真正在容器之间访问状态太多,所以我没有看到很多用于store.getState()的东西,但即使你想要派遣,你需要访问商店,对吧?

所以,除了从'path/to/store/store'导入import store之外

在我想要getState()或"dispatch"的每个文件中,如何访问该状态,因为如果我不包含它,则存储未定义.

And*_*ker 80

通常,您只想制作能够访问商店的顶级容器组件 - 它们会将任何必要的数据或操作调度作为道具传递给其子组件.这是"智能"和"哑"组件之间的区别 - "智能"组件了解Redux存储/状态,而"哑"组件只是将道具传递给他们并且不知道更大的应用程序状态.

然而,即使只是将商店传递给容器组件也会变得乏味.这就是为什么React-Redux提供了一个包装整个应用程序的开箱即用的组件.在文档中查看.这是Provider组件,当您用它包装整个应用程序时,您只需将商店传递给组件一次:

import createStore from '../store';

const store = createStore()

class App extends Component {

  render() {
    return (
      <Provider store={store}>
        <MainAppContainer />
      </Provider>
    )
  }
}
Run Code Online (Sandbox Code Playgroud)

正如你在这里看到的,我有一个单独的配置文件只是为了我的商店,因为你可以做很多修改,对于任何远程复杂的应用程序,你会发现自己也在做同样的事情,比如使用compose来应用中间件.

然后,任何剩余的"智能"组件(通常是包装器)都需要收听商店.这是使用connect方法完成的.这允许您将状态的各个部分映射到组件属性以及将操作作为属性分派.

import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as actionCreators from './actionCreators';

const mapStateToProps = function(state){
  return {
    something: state.something,
  }
}

const mapDispatchToProps = function (dispatch) {
  return bindActionCreators({
    getSomething: actionCreators.getSomething,
  }, dispatch)
}

class MainAppContainer extends Component {

    componentDidMount() {
      //now has access to data like this.props.something, which is from store
      //now has access to dispatch actions like this.props.getSomething
    }

    render() {
        //will pass down store data and dispatch actions to child components
        return (
               <div>
                   <ChildComponent1 something={this.props.something} />
                   <ChildComponent2 getSomething={this.props.getSomething} />
               </div>
        )
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(MainAppContainer)
Run Code Online (Sandbox Code Playgroud)

因为您始终将调度操作和数据作为属性传递给子组件,所以您只需引用该组件上的那些操作和数据this.props.

基于上面的示例,您将看到,因为我传递this.props.somethingChildComponent1它,它可以访问something商店中的数据,但它无权访问getSomething调度操作.同样,ChildComponent2只能访问getSomething调度操作而不能访问something数据.这意味着您只能将组件暴露给他们所需的商店.

例如,因为ChildComponent2传递了调度操作,因为getSomething在我onClick可以调用this.props.getSomething并且它将调用调度操作而不需要任何访问存储.以同样的方式,它可以继续传递getSomething给另一个子组件,该组件可以调用它和/或将其传递下去,并且循环可以无限期地继续.

class ChildComponent2 extends Component {

    render() {
        return (
            <div>
                <div onClick={this.props.getSomething}>Click me</div>
                <NestedComponent getSomething={this.props.getSomething} />
            </div>
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

从评论中编辑

虽然这与问题没有直接关系,但在评论中你似乎对行动有点困惑.我实际上并没有在getSomething这里定义动作.相反,在Redux应用程序中通常会将所有操作定义放在一个名为的单独文件中actionCreators.js.这包含与您的操作命名相同的函数,并返回具有type属性的对象以及操作所需的任何其他方法/数据.例如,这是一个非常简单的示例actionCreators.js文件:

export function getSomething() {
    return {
        type: 'GET_SOMETHING',
        payload: {
            something: 'Here is some data'
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

此操作类型是您的reducer将侦听以了解正在触发的操作的操作类型.

  • 不用担心,伙计.我没有在`getSomething`上设置一个动作类型,甚至没有定义它,因为通常人们在一个名为`actionCreators.js`的单独文件中定义他们应用的所有动作.这将是一个刚刚填充函数的文件,这些函数返回具有`type`属性的对象以及该操作所需的任何其他内容.所以在那个组件上我实际上需要从`actionCreators.js'导入'getSomething`函数以及`redux`中的`bindActionCreators`模块.我省略了那些import语句来清理代码,但我可以将它们添加回来. (2认同)

Gab*_*erg 15

如果您使用该react-redux包装,您将最终将您的组件包装在Provider一个store支柱中.这将在React上下文中设置您的单个存储,然后从connect子组件中的方法访问该上下文.该connect方法有两个函数(mapStateToProps和mapDispatchToProps),它们是从商店获取状态和调度消息的钩子.

请查看此处了解更多信息

  • 那么如果你有10个容器组件,每个容器组件都需要有自己的connect()实现,mapStateToProps()和mapDispatchToProps()?如何节省打字和时间?我认为每个容器组件都可以直接访问商店.原型用例是一个User对象,需要几乎每个子孙组件都可以访问.孩子们如何轻松访问商店内的User对象? (7认同)
  • @Teomanshipahi-我认为让每个组件直接与状态(redux)对话要比无休止地将道具从组件传递给子组件更好,后者知道有多深……这是一件很丑的事情。 (2认同)