Redux与它的中间件

序言

此处要讲的就是二个Redux在React中的应用难点,讲1讲Redux,react-redux,redux-thunk,redux-actions,redux-promise,redux-sage那么些包的成效和她们减轻的标题。
因为不想把篇幅拉得太长,所以并未有太多源码分析和语法疏解,能怎么回顾就怎么回顾。

在React中,常用Redux来做一些事情逻辑管理。
Redux提供了中间件的写法,能够对Redux中的数据流做一些自定义的拍卖(类似于OKHttp的interceptor机制)。

中间件

Middleware 能够让您打包 store 的 dispatch方法来到达你想要的目标。同时,
middleware 还享有“可构成”这1首要天性。三个 middleware
能够被整合到1块儿行使,造成 middleware 链。在那之中,各类 middleware
都不供给关切链中它左右的 middleware 的别的消息。
先是Redux常用的中间件的功力有:日志记录、异步调用等功效。中间件是为着进行程序功效而留存。平时由框架提供落成接口的方案

打造Redux中间件

Redux

先看看百度周全上边Redux的一张图:

Ca88亚洲城官网 1

那是Redux在Github上的介绍:Redux用于js程序,是多少个可预测的情状容器。

Ca88亚洲城官网,在此间大家首先要掌握的是如何叫可预测?什么叫状态容器?

怎么样叫状态?实际上正是变量,对话框显示或隐蔽的变量,1杯奶茶多少钱的变量。

那么那么些景况容器,实际上就是多少个存放那么些变量的变量。

你创造了三个全局变量叫Store,然后将代码中决定各样状态的变量存放在中间,那么以后Store就称为状态容器。

何以叫可预测?

您在操作这些Store的时候,总是用Store.price的办法来安装值,那种操作数据的办法很原始,对于复杂的种类来讲恒久都不知底程序在运营的经过中爆发了如何。

那么今后我们都因此发送一个Action去做修改,而Store在收受到Action后会使用Reducer对Action传递的数额做管理,最终接纳到Store中。

周旋于Store.price的主意来修改者,那种格局确实更麻烦,但是那种方法的裨益正是,每二个Action里面都足以写日记,可以记录各类状态的变动,那正是可预测。

因此只要您的次第很简短,你无需去用Redux。

探访Redux的言传身教代码:

actionTypes.js:

export const CHANGE_BTN_TEXT = 'CHANGE_BTN_TEXT';

Redux与它的中间件。actions.js:

import * as T from './actionTypes';

export const changeBtnText = (text) => {
  return {
    type: T.CHANGE_BTN_TEXT,
    payload: text
  };
};

reducers.js:

import * as T from './actionTypes';

const initialState = {
  btnText: '我是按钮',
};

const pageMainReducer = (state = initialState, action) => {
  switch (action.type) {
    case T.CHANGE_BTN_TEXT:
      return {
        ...state,
        btnText: action.payload
      };
    default:
      return state;
  }
};

export default pageMainReducer;

index.js

import { createStore } from 'redux';
import reducer from './reducers';
import { changeBtnText } from './actions';

const store = createStore(reducer);
// 开始监听,每次state更新,那么就会打印出当前状态
const unsubscribe = store.subscribe(() => {
  console.info(store.getState());
});
// 发送消息
store.dispatch(changeBtnText('点击了按钮'));
// 停止监听state的更新
unsubscribe();

此地就不表明怎么着语法效能了,网络那样的素材太多了。

Ca88亚洲城官网 2

logger中间件的遵从

redux-logger中间件,落成的效应是打字与印刷出一个action发出之后,state的退换的长河。三个简便的例证

actions.js

let nextTodoId = 0
export const addTodo = (text) => ({
  type: 'ADD_TODO',
  id: nextTodoId++,
  text
})

reducers.js

const todos = (state = [], action) => {
  switch (action.type) {
    case 'ADD_TODO':
      return [
        ...state,
        {
          id: action.id,
          text: action.text,
          completed: false
        }
      ]
    default:
      return state
  }
}

export default todos

index.js

import React from 'react';
import ReactDOM from 'react-dom';

import {applyMiddleware,createStore} from 'redux';

import logger from 'redux-logger';

import './index.css';
import App from './App';
import * as actions from './actions';
import reducers from './reducers';
import registerServiceWorker from './registerServiceWorker';

const store = createStore(reducers,applyMiddleware(logger));

store.dispatch(actions.addTodo('add ToDo'));


ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();

如上代码运维结果如下所示:

Ca88亚洲城官网 3

redux-logger.PNG

从运营结果能够见到,dispatch二个addTodo
action后,redux-logger中间件会打字与印刷出action运营此前的state
,然后是action的值,最终是action施行之后的 next
state的值;上面要斟酌的正是如此的3在那之中间件产生的八个历程。

简单的

中央中间件:

const customMiddleware = store => next => action => {
    if(action.type !== 'CUSTOM_ACT_TYPE') {
        return next(action)
        // 其他代码
    }
}

使用:

import {createStore, applyMiddleware} from 'redux';
import reducer from './reducer';
import customMiddleware from './customMiddleware';

const store = createStore(reducer, applyMiddleware(customMiddleware));

store => next => action =>看起来很复杂有木有。基本上你是在写2个1层一层往外再次来到的格局,调用的时候是那般的:

let dispatched = null;
let next = actionAttempt => dispatched = actionAttempt;

const dispatch = customMiddleware(store)(next);

dispatch({
  type: 'custom',
  value: 'test'
});

您做的只是串行化的函数调用,并在每回的调用上传出适当的参数。当自家首先次探望那个的时候,笔者也被这么长的函数调用串惊呆了。不过,在读了编写redux测试从此就理解是怎么回事了。

因而现在大家掌握了函数调用串是怎么工作的了,大家来解释一下那些中间件的首先行代码:

if(action.type !== 'custom') {
    return next(action);
}

应当有怎么样措施能够分别哪些action能够被中间件使用。在那几个事例里,大家看清action的type为非custom的时候就调用next措施,别的的会传导到别的的中间件里领悟reducer。

Redux与React的结合:react-redux

Redux是3个可预测的图景容器,跟React那种营造UI的库是四个互相独立的事物。

Redux要使用到React中,很显著action,reducer,dispatch那多少个级次并无需改变,唯1须要挂念的是redux中的状态需求哪些传递给react组件。

很简单,只需求每趟要翻新数据时行使store.getState获取到当下情景,并将这么些数据传递给组件就能够。

那便是说难题来了,怎么着让各样组件都取获得store呢?

理所当然是将store作为三个值传递给根组件,然后store就能超级一流往下传,使得各样组件都能获得到store的值。

但是这么太烦琐了,难道每种组件供给写二个传递store的逻辑?为了缓和那些主题材料,那么得用到React的context玩的方法,通过在根组件校官store放在根组件的context中,然后在子组件中通过context获取到store。

react-redux的关键思路也是那般,通过嵌套组件Provider将store放到context中,通过connect这一个高阶组件,来隐藏取store的操作,那样我们就不需求每一回去操作context写一大堆代码那么麻烦了。

然后大家再来基于此前的Redux示例代码给出react-redux的选用演示代码,当中action和reduce部分不改变,先扩充2个组件PageMain:

const PageMain = (props) => {
  return (
    <div>
      <button onClick={() => {
        props.changeText('按钮被点击了');
      }}
      >
        {props.btnText}
      </button>
    </div>
  );
};
// 映射store.getState()的数据到PageMain
const mapStateToProps = (state) => {
  return {
    btnText: state.pageMain.btnText,
  };
};
// 映射使用了store.dispatch的函数到PageMain
const mapDispatchToProps = (dispatch) => {
  return {
    changeText: (text) => {
      dispatch(changeBtnText(text));
    }
  };
};

// 这个地方也可以简写,react-redux会自动做处理
const mapDispatchToProps = {
  changeText: changeBtnText
};

export default connect(mapStateToProps, mapDispatchToProps)(PageMain);

小心下边包车型大巴state.pageMain.btnText,这么些pageMain是本人用redux的combineReducers将五个reducer合并后给的原来的reducer三个命名。

它的代码如下:

import { combineReducers } from 'redux';
import pageMain from './components/pageMain/reducers';

const reducer = combineReducers({
  pageMain
});

export default reducer;

接下来修改index.js:

import React from 'react';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import ReactDOM from 'react-dom';
import reducer from './reducers';
import PageMain from './components/pageMain';

const store = createStore(reducer);

const App = () => (
  <Provider store={store}>
    <PageMain />
  </Provider>
);

ReactDOM.render(<App />, document.getElementById('app'));

9c456d5d211602e9d742262c2bf45762_b.png-23.6kB

最原始的得以完成

假使要提供以上的logger成效,有2个最棒轻便的方法,即替换掉store.dispatch方法:

import React from 'react';
import ReactDOM from 'react-dom';

import {applyMiddleware,createStore} from 'redux';

// import logger from 'redux-logger';

import './index.css';
import App from './App';
import * as actions from './actions';
import reducers from './reducers';
import registerServiceWorker from './registerServiceWorker';

// const store = createStore(reducers,applyMiddleware(logger));

const store = createStore(reducers);


let dispatch = store.dispatch;
//替换掉store原始的dispatch
store.dispatch = (action) => {
    console.log('prev state',store.getState());
    console.log('dispatch',action);
    let result = dispatch(action);
    console.log('next state',store.getState());

    return result;
}


store.dispatch(actions.addTodo('add ToDo'));


ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();

那般就能够在发布action在此以前和之后都打字与印刷出state的值了。尽管那只是四个很简短的交替store的dispatch,可是真的实现了那些效果,而那也是redux中间件最中央的肆项。别的的都感到着扩张性而围绕着这么些基本设计的。

来点酷的

redux的合法指点里有多少个不利的例证,作者在此间详细解释一下。

我们有三个如此的action:

dispatch({
  type: 'ajax',
  url: 'http://some-api.com',
  method: 'POST',
  body: state => ({
    title: state.title,
    description: state.description
  }),
  cb: response => console.log('finished', response)
})

大家要得以落成一个POST请求,然后调用cb本条回调方法。看起来是那样的:

import fetch from 'isomorphic-fetch'

const ajaxMiddleware = store => next => action => {
    if(action.type !== 'ajax') return next(action);

    fetch(action.url, {
        method: action.method,
        body: JSON.stringify(action.body(store.getState()))
    }).then(response => response.json())
    .then(json => action.cb(json))
}

可怜的简练。你能够在中间件里调用redux提供的每3个方法。如若大家要回调方法dispatch越来越多的action该怎么样管理吧?

.then(json => action.cb(json, store.dispatch))

假若修改上例的末尾一行就足以消除。

接下来在回调方法定义里,我们得以如此:

cb: (response, dispatch) => dispatch(newAction(response))

As you can see, middleware is very easy to write in redux. You can pass
store state back to actions, and so much more. If you need any help or
if I didn’t go into detail enough, feel free to leave a comment below!

如你所见,redux中间件万分轻易完结。

初稿地址:https://reactjsnews.com/redux-middleware

网站地图xml地图