美文网首页
【深入react技术栈】深入Redux应用架构

【深入react技术栈】深入Redux应用架构

作者: 不会嘤嘤嘤的程序媛 | 来源:发表于2018-07-06 18:57 被阅读0次

    Redux简介

    1. Redux三大原则

    • 单一数据源
    • 状态是只读的
    • 状态的修改均由纯函数完成

    2. Redux 核心API

    核心:store,由createStore(reducers[,initialState])方法生成。

    reducer负责响应action并根据previousState和action修改数据。reducer(previousState,action)=>newState

    import {createStore} from 'redux';
    const store = createStore(reducers);
    // 此处 store是一个对象,包含4个方法
    
    • getState():获取store中当前的状态。
    • dispatch(action):分发一个action,并返回这个action,这是唯一能改变store中数据的方式。
    • subscribe(listener):注册一个监听者,在store变化时被调用。
    • replaceReducer(nextReducer):更新当前store里的reducer,一般只会在开发模式中调用该方法。

    3. 与 React 绑定

    react-redux库提供 React 绑定。提供了:

    <Provider/>组件:接受一个store作为props,它是整个Redux应用的顶层组件。

    connect()API:提供了在整个React应用的任意组件中获取store中的数据的功能。

    Redux中间件

    Redux middleware,提供了一个分类处理action的机会。

    import compose from './compose';
    
    export default function applyMiddleware(...middlewares) {
      return (next) => (reducer, initialState) => {
        // 获取得到原始的store
        let store = next(reducer, initialState);
        let dispatch = store.dispatch;
        // 赋值一个空数组,用来存储后新的dispatch分裂函数
        let chain = [];
    
        var middlewareAPI = {
          getState: store.getState,
          dispatch: (action) => dispatch(action)
         };
    
        chain = middlewares.map(middleware => middleware(middlewareAPI));
        // 将分裂的函数组合每次都会执行,即每次都执行这些中间件函数
        dispatch = compose(...chain)(store.dispatch);
    
        return {
          ...store,
          dispath
        }
      }
    }
    
    函数式编程思想设计

    通过函数式编程中的 currying。currying 的middleware结构的好处有以下两点

    • 易串联

    不断currying形成的middleware可以累积参数,再配合组合方式,很容易形成 pipeline来处理数据流

    • 共享store

    applyMiddleware执行过程中,store还是旧的,applyMiddleware完成后,所有的middleware内部拿到的sotore都是最新且相同的

    // 使用中间件增强createStore函数
    let newStore = applyMiddleware(mid1, mid2, mid3)(createStore)(reducer, null);
    // 组合串联中间件
    dispatch = compose(...chain)(store.dispatch)
    
    redux-thunk

    store.dispatch(action),正常情况下参数只能是对象,不能是函数,中间件redux-thunk改造dispatch后就可以使参数为函数。

    const thunk = store => next => action => {
      typeof action === 'function' ?
        action(store.dispatch, store.getState) :
        next(action)
    }
    

    Redux 异步流

    使用 middleware 简化异步请求

    redux-thunk
    function getWeather(url, params) {
       return (dispatch, action) {
        fetch(url, params)
          .then(result => {
            dispatch({
              type: 'GET_WEATHER_SUCCESS',
              payload: result,
            })
          })
          .catch(err => {
            dispatch({
              type: 'GET_WEATHER_ERROR',
              payload: err,
            })
          })
      }
    }
    // 调用store.dispatch(getWeather),redux-thunk就会执行getWeather方法
    
    redux-promise

    返回的结果保存在payload中

    const fetchData = (url, params) => fetch(url, params);
    async function getWeather(url, params) {
        const result = await fetchData(url, params);
        if (result.error) { 
            return {
                type: 'GET_WEATHER_ERROR',
                error: result.error
            };
        }
        return {
            type: 'GET_WEATHER_SUCCESS',
            payload: result
        };
    }
    

    使用middleware处理复杂异步流

    redux-saga

    用generator代替promise

    Redux与路由

    React Router

    在声明路由时,path属性指明了当前路由匹配的路径形式。若需要参数,可以用:参数名即可。若这个参数是可选参数,则用括号套起来(:参数名)

    import { Router,Route,IndexRoute,browserHistory} from 'react-router';
    const routers = (
      <Router history={browserHistory}>
          <Route path="/" component={App}>
             <IndexRoute component={MailList} />
             <Route path="/mail/:mailId" component={Mail} />
          </Route>
      </Router>
    )
    
    支持多种路由切换方式

    hashChange ---- hashHistory(作为props传给Router)

    history.pushState --- browserHistory(作为props传给Router)

    React Router Redux

    1. 将 React Route 与 Redux Store 绑定

    React Router Redux提供了API--syncHistoryWithStore来完成绑定,参数为需要传入React Router中的hostory和 Redux中的store,获得一个增强后的history对象

    import {browsweHistory} from 'react-router';
    import {syncHistoryWithStore} from 'react-router-redux';
    import reducers from '<project-path>/reducers';
    
    const store = createStore(reducers);
    const history = syncHistoryWithStore(browserHistory,store);
    
    2. 用 Redux 方式改变路由

    Redux 应用中改变路由时,要分发一个action。在此之前,需要对store进行一些增强,以便action能被正确识别。

    import {browsweHistory} from 'react-router';
    import {routerMiddleware} from 'react-router-redux';
    
    const middleware = routerMiddleware(browserHistory);
    const store = createStore(
        reducers,
        applyMiddleware(middleware);
    );
    

    最后用store.dispatch分发一个路由变动的action

    import {push} from 'react-router-redux';
    // 切换路由到 /home
    store.dispatch(push('/home'));
    

    Redux 与组件

    容器型组件

    redux中使用connect的组件,做了数据更新的定义。不包含任何虚拟DOM 的修改和组合,也不含样式

    展示型组件

    包含虚拟DOM的修改或组合,也可能有样式。不依赖store,可以写成无状态函数。

    相关文章

      网友评论

          本文标题:【深入react技术栈】深入Redux应用架构

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