redux——入门2

作者: 我只是个NPC | 来源:发表于2017-03-30 15:52 被阅读30次

    redux——入门1里面,我简要介绍了redux的核心概念,并举了一个简单的计数器demo的例子,用于展示在react中怎么使用redux。现在,我打算把这个简单的demo变得复杂一点,引入react-redux和redux中一些其他的概念。

    工具分享

    在本篇正式开始之前,我想先分享一个用于快速构建react应用的脚手架工具,传送门:https://github.com/facebookincubator/create-react-app

    概念引入

    我会在这个升级版的demo里面,引入三个东西,Provider(react-redux),combineReducers(redux),connect(react-redux),如果你想更深入的了解react-redux中的各个角色,这里有个很好的解释https://github.com/jasonslyvia/a-cartoon-intro-to-redux-cn

    Provider

    这是一个组件,没有其他特殊的作用,但是我们需要将它包裹在整个组件树的最外层,只有这样,其内部的子孙组件才能使用connect来绑定store。

    connect

    这是一个函数,由react-redux提供,其返回依然是一个函数,该函数会处理视图与store绑定的细节,具体的使用方法后面会做介绍。

    combineReducers

    这也是一个函数。在上一章,我们的reducer是一个单一的函数,在处理类似于计数器这样的简单应用时,我们不会看出有什么问题,但是当整个系统变得复杂后,单一的reducer就会变得臃肿不堪,所以我们需要对reducer进行分片,每一个reducer用于单独处理一部分state,而combineReducers就是将分片的reducer合并为一个整体,这个函数的实现也比较简单。

    counter升级版

    因为参照了react的官方示例,因此整个例子所使用的语法和上个简化版的例子会有比较大的出入。

    入口文件index.js

    import React from 'react';
    import ReactDOM from 'react-dom';
    import {createStore} from 'redux';
    import {Provider} from 'react-redux';
    import reducer from './reducers';
    import Root from './components/root';
    
    let store = createStore(reducer);
    
    ReactDOM.render(
      <Provider store={store}>
        <Root></Root>
      </Provider>,
      document.getElementById('root')
    );
    

    同简化版本相比,这里我们引入了Provider,并将其包裹在了组件的最外层。

    reducers/index.js

    import {combineReducers} from 'redux';
    import counter from './counter';
    
    const all = combineReducers({
      count: counter
    });
    
    export default all;
    

    在这里,我们调用了combineReducers方法,将counter这个reducer合并到主reducer上,因为计数器这个demo很简单,所以我们只将state划分了一个属性count,而counter这个reducer和简化版的没有什么区别,姑且还是贴一下代码

    export default (state=0, action) => {
    
      switch(action.type) {
        case 'INCREMENT': 
          return state + 1;
        case 'DECREMENT': 
          return state - 1;
        default: 
          return state;
      }
    }
    

    前面说过,combineReducer的实现其实是蛮简单的,其实就是返回一个函数,每次处理action的时候,这个函数会遍历所有的reducer来处理这个action,然后将所有结果打包返回,代码和下面类似

    // combineReducers
    const combineReducers = ( reducers ) => {
        return ( state = {}, action ) => {
            return Object.keys(reducers).reduce(
                ( nextState, key ) => {
                    nextState[key] = reducers[key](
                        state[key],
                        action
                    );
                    return nextState;
                },
                {}
            );
        };
    };
    

    components/root.js

    这是我们的根组件

    import React from 'react';
    import InputBox from '../containers/input-box';
    import ShowBox from '../containers/show-box';
    
    export default () => {
      return (
        <div>
          <InputBox></InputBox>
          <ShowBox></ShowBox>
        </div>
      );
    };
    

    这个没什么可以讲的,主要看接下来的InputBox和ShowBox

    containers/input-box

    这是一个纯输入组件

    import React from 'react';
    import {connect} from 'react-redux';
    
    let InputBox = ({onIncrement, onDecrement}) => {
    
      return (
        <div>
          <button type="button" onClick={onIncrement}>+++</button>
          <button type="button" onClick={onDecrement}>---</button>
        </div>
      );
    };
    
    let mapDispatchToProps = (dispatch) => ({
      onIncrement: () => dispatch({type: 'INCREMENT'}),
      onDecrement: () => dispatch({type: 'DECREMENT'})
    });
    
    InputBox = connect(undefined, mapDispatchToProps)(InputBox);
    
    export default InputBox;
    

    在这里我们调用了react-redux的connect方法,当然,如果之前完全没接触过connect函数,看这段代码可能会有点头疼,可以先移步这里connect的api文档。我也可以简单介绍下connect的使用方法,它支持四个参数,我这里只介绍前两个,后两个因为我并没怎么用过,所以暂时不讲。
    第一个参数是mapStateToProps(state, [ownProps]),用于选择性的将state中的属性注入到组件的props中,我在show-box中使用了这个参数,所以请看后面的代码。
    第二个参数是mapDispatchToProps(dispatch, [ownProps]),用于将需要触发dispatch的方法,注入到组建的props中,在上面的input-box中,我使用了这个参数,将onIncrementonDecrement两个用于dispatch的方法注入到了InputBox中。

    container/show-box

    这是一个纯展示的组件

    import React from 'react';
    import {connect} from 'react-redux';
    
    let ShowBox = ({count}) => {
      return (
        <div>
          <p>{count}</p>
        </div>
      );
    };
    
    let mapStateToProps = (state) => ({
      count: state.count
    });
    
    ShowBox = connect(mapStateToProps)(ShowBox);
    
    export default ShowBox;
    

    唯一需要注意的是用了mapStateToProps

    总结

    虽然是说是升级版,但也只是多引入了几个东西,总体来说还是算简单,只是概念多了,容易让人糊涂,我被绕了一个上午,好在现在总算有点清醒了,所以记下这些东西,方便之后的回顾。

    相关文章

      网友评论

        本文标题:redux——入门2

        本文链接:https://www.haomeiwen.com/subject/qyxpottx.html