react-redux的实现原理

其实React与Redux并没有什么直接的联系。Redux作为一个通用模块,主要还是用来处理应用中state的变更,而展示层不一定是React。
但当我们希望在React+Redux的项目中将两者结合的更好,可以通过react-redux做连接。

当一个react项目组件层级越来越深,页面越来越多的时候,数据在各个组件层级和页面之间传递的需求就会比较多,很多变量也需要做成可全局管理的。在这个时候,redux和react-redux的使用就很有必要了。它们能帮助我们很方便的进行项目全局性的数据管理。

一、redux和React-redux的几个重要概念

1. state

整个应用的状态

1. action

Action 是把数据从应用传到 store 的有效载荷。它是 store 数据的唯一来源。一般来说你会通过 store.dispatch() 将 action 传到 store。

2. reducer

Reducers 指定了应用状态的变化如何响应 actions并发送到 store 的,记住 actions 只是描述了有事情发生了这一事实,并没有描述应用如何更新 state。

3. store

store就是把action和reducer联系到一起的对象,一个redux应用只能有一个store。任何组件都可以直接从store访问特定对象的状态。

在 Redux 中,state数据保存在一个store容器中 ,当一个store接收到一个action,它将把这个action代理给相关的reducer。reducer是一个纯函数,它可以查看之前的状态,执行一个action并且返回一个新的状态。

react-redux

react-redux 若用 redux,一个组件如果想从store存取公用状态,需要进行四步操作:

       (1)import 引入 store

       (2)getState 获取状态

       (3) dispatch 修改状态

       (4)subscribe 订阅更新

代码相对冗余,我们想要合并一些重复的操作,而 react-redux 就提供了一种合并操作的方案,react-redux是一个轻量级的封装库,核心方法只有两个:

  • Provider  Provider 将 store 放进 this.context 里,省去了 import 这一步
  • connect   connect将 getState、dispatch 合并进了this.props,并自动订阅更新,简化了另外三步。

Provider

Provider 其实就只是一个外层容器,它的作用就是通过配合 connect 来达到跨层级传递数据。使用时只需将Provider定义为整个项目最外层的组件,并设置好store。那么整个项目都可以直接获取这个store。它的原理其实是通过React中的[Context]()来实现的。
import React from 'react'
import PropTypes from 'prop-types'
export class Provider extends React.Component {
  // 需要声明静态属性childContextTypes来指定context对象的属性,是context的固定写法  
  static childContextTypes = {
    store: PropTypes.object
  }

  // 实现getChildContext方法,返回context对象,也是固定写法  
  getChildContext() {
    return { store: this.store }
  }

  constructor(props, context) {
    super(props, context)
    this.store = props.store
  }

  // 渲染被Provider包裹的组件  
  render() {
    return this.props.children
  }
}

connect

connect 的作用是连接React组件与 Redux store,它包在我们的容器组件的外一层,它接收上面 Provider 提供的 store 里面的 state 和 dispatch,传给一个构造函数,返回一个对象,以属性形式传给我们的容器组件。

它共有四个参数mapStateToProps, mapDispatchToProps, mergeProps以及options。

mapStateToProps 的作用是将store里的state(数据源)绑定到指定组件的props中 mapDispatchToProps 的作用是将store里的action(操作数据的方法)绑定到指定组件的props中 另外两个方法一般情况下使用不到

connect的调用方式:connect(mapStateToProps, mapDispatchToProps)(App)

export function connect(mapStateToProps, mapDispatchToProps) {
  return function (Component) {
    class Connect extends React.Component {
      componentDidMount() {
        //从context获取store并订阅更新          
        this.context.store.subscribe(this.handleStoreChange.bind(this));
      }
      handleStoreChange() {
        // 触发更新          
        // 触发的方法有多种,这里为了简洁起见,直接forceUpdate强制更新,读者也可以通过setState来触发子组件更新          
        this.forceUpdate()
      }
      render() {
        return (
          <Component
            // 传入该组件的props,需要由connect这个高阶组件原样传回原组件              
            {...this.props}
            // 根据mapStateToProps把state挂到this.props上              
            {...mapStateToProps(this.context.store.getState())}
            // 根据mapDispatchToProps把dispatch(action)挂到this.props上              
            {...mapDispatchToProps(this.context.store.dispatch)}
          />
        )
      }
    }
    //接收context的固定写法      
    Connect.contextTypes = {
      store: PropTypes.object
    }
    return Connect
  }
}
原文地址:https://www.cnblogs.com/SF9924/p/14164762.html