美文网首页
Redux 和 React-redux 使用指南

Redux 和 React-redux 使用指南

作者: 风之化身呀 | 来源:发表于2019-04-08 16:35 被阅读0次

    1、引入Redux

    • createStore 方法
     let store = createStore(todoApp, initialState, process.env.NODE_ENV === 'development' ? window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() : null)
    

    注意点:
    1、由于React代码都要经过webpack处理的,所以在写React代码的时候,可以大致看成代码环境处于Node.js,所以上述的process.env 对象也就可以看成全局变量了,从而可以写区分环境的代码。
    2、createStore第一个参数是reducer,即combineReducer的结果;第二个参数表示store的初始状态(可选);第三个参数表示是否启用Redux调试工具(通常是chrome的一个扩展工具)
    3、store是一个对象,当传入initialState时,其初始值由initialState决定;不传时,由combineReducer的参数(也是一个对象,记为O)决定。需要注意的是对象store的key由O决定,而不是initialState决定,initialState只能传和O有相同属性的值
    4、store的运转过程:1、dispatch(actionCreator(payload));2、reducer处理对应的action,从而修改store
    5、connect函数的两个参数:mapStateToProps(state,ownProps) 和 mapDispatchToProps(dispatch,ownProps)

    const mapStateToProps = state => {
      return {
        todos: getVisibleTodos(state.todos, state.visibilityFilter)
      }
    }
    
    const mapDispatchToProps = dispatch => {
      return {
        onTodoClick: id => {
          dispatch(toggleTodo(id))
        }
      }
    }
    const VisibleTodoList = connect(
      mapStateToProps,
      mapDispatchToProps
    )(TodoList)
    

    任何时候,只要 Redux store 发生改变,mapStateToProps 函数就会被调用。该回调函数必须返回一个纯对象,这个对象会与组件的 props 合并。如果你省略了mapStateToProps 这个参数,你的组件将不会监听 Redux store。如果指定了该回调函数中的第二个参数 ownProps,则该参数的值为传递到组件的 props,而且只要组件接收到新的 props,mapStateToProps 也会被调用(例如,当 props 接收到来自父组件一个小小的改动,那么你所使用的 ownProps 参数,mapStateToProps 都会被重新计算)。就是说不管store的变化是否是你关心的,你的mapStateToProps总是会被调用(即使这次调用是不必要的)
    6、redux 如果不加中间件,则只能处理同步action

    2、 Redux应用状态划分

    • 应用状态扁平化
      这里可以借助 normalizr 库,它可扁平化深层嵌套的json数据。比如下面这个博客数据:
    {
      "id": "123",
      "author": {
        "id": "1",
        "name": "Paul"
      },
      "title": "My awesome blog post",
      "comments": [
        {
          "id": "324",
          "commenter": {
            "id": "2",
            "name": "Nicole"
          }
        },
       {
          "id": "325",
          "commenter": {
            "id": "3",
            "name": "Tom"
          }
        }
      ]
    }
    

    可以扁平化成这样:

    {
      result: "123",
      entities: {
        "articles": {
          "123": {
            id: "123",
            author: "1",
            title: "My awesome blog post",
            comments: [ "324" ]
          }
        },
        "users": {
          "1": { "id": "1", "name": "Paul" },
          "2": { "id": "2", "name": "Nicole" }
        },
        "comments": {
          "324": { id: "324", "commenter": "2" }
        }
      }
    }
    

    所经过的操作如下:

    import { normalize, schema } from 'normalizr';
    
    // Define a users schema
    const user = new schema.Entity('users');
    
    // Define your comments schema
    const comment = new schema.Entity('comments', {
      commenter: user
    });
    
    // Define your article
    const article = new schema.Entity('articles', {
      author: user,
      comments: [comment]
    });
    
    const normalizedData = normalize(originalData, article);
    
    • 抽离公共状态
      待续。。
    • 修改应用状态
      1、Object.assign/Spread Operator
        switch (action.type){
            case SET_VISIBILITY_FILTER:
                return {...state,visibilityFilter: action.filter}
            default:
                return state;
        }
    }
    

    2、Immutable.js 或者 Seamless-Immutable.js

    3、实现

    • 简易版Redux(主要就是实现createStore,返回三个方法:getState,dispatch,subscribe。以及applyMiddleWare函数)
    const createStore = reducer => {
        let state = null;
        const listeners = [];
        const getState = () => state;
        const subscribe = listener => listeners.push(listenter);
        const dispatch = action =>{
            state = reducer(state,action);
            listeners.forEach(listenter => listenter());
        };
        dispatch({});
        return {
            getState,
            dispatch,
            subscribe
        }
    }
    // 用法
    const colorReducer = (state,action) => {
        if(!state){
            return {
                color:red
            }
        }else{
            switch(action.type){
                case 'modifyColor':
                    return {
                      ...state,
                      color:action.color
                  }
                default:
                    return state;
            }
        }
    }
    const store = createStore(colorReducer);
    store.dispatch({type:'modifyColor',color:'green'})
    
    • applyMiddleware 实现
    const applyMiddleWare = (...middlewares) => next =>{
        return (reducer,initialState) =>{
            let store = next(reducer,initialState);
            let dispatch = store.dispatch;
            let chain = [];
            let middlewares = middlewares;
            const middlewareAPI = {
                getState: store.getState,
                dispatch: action => dispatch(action)
            }
            chain = middlewares.map(value => value(middlewareAPI))
            dispatch = compose(...chain )(store.dispatch)
            return {
                ...store,
                dispatch
            }
        }
    }
    
    function compose(...funcs) {
        return arg => funcs.reduceRight((composed, f) => f(composed), arg);
    }
    
    • 简易版React-redux (主要就是实现connect高阶函数以及Provider组件)
    const connect = (mapStateToProps,mapDispatchToProps) => WrappedComponent =>{
        class Connect extends Component {
            static contextType = {
                store: PropTypes.object
            }
            constructor(){
                this.state = {
                    allProps:{}
                }
            }
            componentWillMount(){
                this._updateProps();
                this.context.store.subscribe(()=>this._updateProps());  // 订阅dispatch的变化,只要有dispatch,就会重新调用_updateProps,从而重新调用mapStateToProps和mapDispatchToProps触发React组件的生命周期,更新组件
            }
            _updateProps(){
                const store = this.context.store;
                const allProps = {};
                const mapProps = mapStateToProps(store.getState(),this.props);
                const mapDispatch = mapDispatchToProps(store.dispatch,this.props);
                this.setState({
                    allProps: {
                        ...this.props,
                        ...mapProps,
                        ...mapDispatch
                    }
                })
                
            }
            render(){   
                return <WrappedComponent ...this.state.allProps />
            }
        }
        return Connect
    }
    
    class Provider extends Component{
        static propTypes = {
            store: PropTypes.object,
            children: PropTypes.any
        }
        static childContextType = {
            store: PropTypes.object
        }
        getChildContext(){
            return {
                store:this.props.store || {}
            }
        }
        render(){
            return(
                <div>this.props.children</div>
            )
        }
    }
    
    • 中间价的写法:
    // 签名:
    ({dispatch, store}) => (next) => (action) => {}
    

    参考

    相关文章

      网友评论

          本文标题:Redux 和 React-redux 使用指南

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