react-redux(一)

Redux着眼于对状态整理的维护,而不会产生出具体变动的部分。React是一个由状态整体输出界面的view层实现,因此二者可以说是绝配。

如何在React项目中使用Redux


当我们在说如何使用Redux时,说的其实是如何获取并使用store内容(状态数据),以及创建并触发action的过程。

一. 获取并使用store


  • 属性传递store状态数据
    Redux的特点是整个应用的状态信息保存在一个store中,因而需要由store将数据从React组件树节点传入。为了在数据变化时更新界面,还需要对store进行监听:
function render() {
    const state = store.getState();
    React.render(
      ,
      document.getElementById('app')
    );
}

store.subscribe(render);
render();

这样,在组件App中,可以通过this.props.state获取状态信息。组件App可以进一步将状态信息以props的形式传递给其子孙节点:

class App extends React.Component {
    render() {
        return (
          
); } }

正如例子中的组件Header,每个组件都可以从上层节点获取它所需的信息。
然而,当项目规模变大,组件层级变多时,情况会急剧恶化,因为如果某个组件处在组件数第n级,那么没修改一个属性或增加一个组件,都需要改动n-1处,这是无法想象的维护成本。
下面是很自然思考到的解决这个问题的办法

  • 组件自行获取store状态数据

对应的的做法是,把createStore的结果通过一个独立的模块以module export的方式暴露出来,所有组件都可以直接去import这个模块得到store,然后对store进行subscribe:

// store.js
import reducers from 'reducers';
export default createStore(reducers);
// TodoFilter.js
import store from 'store';
export default class TodoFilter extends React.Component {
    constructor() {
        super();
        this.state = {
            filter: null
        };
    }
    componentDidMount() {
        store.subscribe(() => {
            this.setState({
                filter: store.getState().filter
            });
        });
    }
    render() {
        // 界面渲染
    }
}

在组件挂载完成后监听store的变化,取出最新状态数据,并通过组件自身的setState方法更新组件的state信息,自动触发重新渲染组件界面。
通过这种方式,我们顺利地解决了前面遇到的问题,但依然存在一些问题:

  1. 组件私自与store建立联系,致数据流难以追溯。
  2. 拥有内部state的组件不便于测试。
  3. 每个需要访问store组件都实现一份subscript&setState这样的逻辑略显繁琐。

react-redux将是上面这些问题较为成熟的、通用的解决方案。

二. 创建与触发action


在Flux架构中,store的状态改变必须由action引起,除了获取与使用store状态数据外,另外一个与store打交道的方式便是创建与触发action。在Redux中,这个过程包含两个部分:

  1. 创建action,使用actionCreator
  2. 触发action,通过store.dispatch将action作用到特定的store上

不难发现,触发action的方法dispatch,也面临着一样的问题,就是获取store。下面介绍针对这一问题的官方答案:react-redux。

react-redux


react-redux是Redux官方提供的React绑定,用于辅助在React项目中使用Redux,性能优异且灵活强大。API相当简单,包括一个Provider组件和一个connect高阶方法。

  • Provider

Provider是store提供者。只要把组件树根节点包裹在Provider中,整个组件树上的节点都可以通过connect获取store:

ReactDOM.render(
  
    
  
);
  • connect

connect是用来“连接”store与组件的方法,用法如下:

import { add } from 'actions';

function mapStateToProps(state) {
    return {
        num: state.num
    };
}

function mapDispatchToProps(dispatch) {
    return {
        onBtnClick() {
            dispatch(add()); // add()为action creator
        }
    };
}

function Counter(props) {
    return (
      

{props.num}

); } export default connect(mapStateToProps, mapDispatchToProps)(Counter);

在这个示例中,我们通过connect让组件Counter得以连接store,从store中取得num信息并在按钮单击时触发store上的add方法。

  • enhancer

connect()的执行结果是一个“高阶组件”,我们称之为enhancer。
高阶组件指符合以下条件的函数:接收一个已有的组件作为参数,返回一个新组件,后者将前者封装于内部。一般使用高阶组件都是为了对已有组件进行某些能力上的增强。
这里enhancer对传入组件进行怎样的增强呢?答案便是接触store的能力。
原有组件Counter不直接与store打交道,甚至不知道store与Redux的存在,而经过enhancer处理得到的组件,即上例中最终被export的内容,能够直接接触到store,监听、读取状态数据并触发action。这里的store,就是先前通过Provider引入的。

react-redux通过React在0.1.4版引入的context特性实现了store内容的隐式传递:Provider作为整个组件树的根节点,通过实现getChildContext方法将store提供给它的的子孙们,而enhancer通过组件的context属性获取store对象,从而可以调用其提供的subscript、getState、dispatch等方法。

你可能感兴趣的:(react-redux(一))