[译] 理解 React-redux connect

[译] 理解 React-redux connect

Redux 是一个非常简单库,主要目的是进行状态管理,它使得 React 开发变得更加容易。然鹅很多人都只是简单的使用 Redux 官网提供的样板代码,把它和 React 应用结合起来,却并不理解这两者到底是如何结合并且运作的。

有一个库叫做 React-redux,它唯一的目的就是把 redux 的状态管理机制无缝衔接到 react 应用上。我认为当使用了一些构成了你应用核心的东西的时候,还是非常应该了解具体发生了什么的。

React 和 redux 本身

对于某些人来说,也许很难相信 redux 和 react 实际上是两个独立的库这件事情,它们完全可以独立使用。

我们先来看一下 redux 的状态(state)管理机制:

redux flow

如果你之前曾经使用过 redux,你就知道 redux 主要是围绕着 "store" 来运转的,它的 store 就是用来保存应用里所有的 state 的地方。任何人都不能直接修改 store,只能通过 reducers 来修改 store 里的数据,而想要触发 reducers 我们需要派发 actions。所以最终:

To change data, we need to dispatch an action

想要改变数据,我们需要派发一个 action

另一方面,如果我们想要获取数据,也不能直接从 store 里取。而是通过 store.getState() 来得到当时 store 里所有数据的 “快照”,也即是获取了我们调用 getState 时整个程序的状态

To obtain data we need to get the current state of the store

想要获取数据,我们需要得到 store 里的状态

接下来我们看一下一个标准 React todo 应用的组件结构。

react flow

把 React 和 Redux 结合起来

如果想把 redux store 和我们的 react 应用链接起来,那么首先需要让应用知道 store 的存在。这也即是 react-redux 库的第一个主要部分 Provider

Provider 其实是 react-redux 提供的一个 React 组件,它只有一个作用,就是把 store “提供 provide” 给它的子组件。

//This is the store we create with redux's createStore method
const store = createStore(todoApp,{})

// Provider is given the store as a prop
render(
  <Provider store={store}>
    <App/>
  </Provider>, document.getElementById('app-node'))

既然只有 provider 的子组件能获取到 store,而我们一般又希望能让整个应用获取到 store,那么最明智的做法就是把 App 组件放到 Provider 里。

按照上面两幅图的思路,我们应该把 Provider 放在 App 上面表示是 App 的父组件,然而考虑到 Provider 提供的功能,把它表示成包裹着整个应用树的形式更为合适,如下图:
react flow provider

Connect

既然已经把 redux store “provide” 给了我们的应用,接下来就可以把应用里的组件和它 connect 起来了。还记得前面强调的不能直接和 store 交互吗?我们只能通过获取应用的状态来获取 store 里的数据,或者通过派发 action 来改变应用的状态:我们只能获取到上面 redux 流程图里最顶部(dispatch)和最底部(State)的元素。

这些正是 connect 的功能:把 redux 的 dispatch 和 state 映射为 react 组件的 props!(看下面这段代码)

import {connect} from 'react-redux'

const TodoItem = ({todo, destroyTodo}) => {
  return (
    <div>
      {todo.text}
      <span onClick={destroyTodo}> x </span>
    </div>
  )
}

const mapStateToProps = state => {
  return {
    todo : state.todos[0]
  }
}

const mapDispatchToProps = dispatch => {
  return {
    destroyTodo : () => dispatch({
      type : 'DESTROY_TODO'
    })
  }
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(TodoItem)

mapStateToPropsmapDispatchToProps 是两个春函数,分别用来获取 store “state” 和 “dispatch” 。具体来说,这两个函数各返回一个对象,对象的 keys 将作为 props 传递给它们所连接的组件。

这上面这个例子中,mapStateToProps 返回了一个对象只有一个 key: todomapDispatchToProps 返回了一个拥有 key destroyTodo 的对象。

被连结的组件(也就是最后被 export 的那个组件),把 tododestroyTodo 传递给 TodoItem 做 props。
final connect flow

尤其需要注意的是,只有在 Provider 内的组件才能被连结(connect)。从上面的图表可以看到,连结是通过 Provider 建立的。

Redux 是一个非常强大的工具,尤其是当与 React 组合在一起使用时。明白 react-redux 的各个部分是如何使用以及为什么使用会很有帮助,希望阅读完这篇文章,你能清楚 Provider 和 'connect' 的具体功能。

原文 React-redux "connect" explained 链接