Redux 异步+Middleware

Middleware

在构建store时将middleware作为第二个参数;

import { createStore, combineReducers, applyMiddleware, compose } from 'redux';
const logger = store =>{
    return next => {
        return action=>{
            console.log('[Middleware] Dispatching', action);
            const result = next(action);        //将action 传入 reducer
            console.log('[Middleware] next state', store.getState())
            return result;
        }
    }
}

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

Devtools

https://github.com/zalmoxisus/redux-devtools-extension

将Middleware包住,在浏览器中调用reduxdev tools;

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, combineReducers, applyMiddleware, compose } from 'redux';

import counterReducer from './store/reducers/counter';
import resultReducer from './store/reducers/result';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';

const rootReducer = combineReducers({
    ctr: counterReducer,
    res: resultReducer
});


const logger = store =>{
    return next => {
        return action=>{
            console.log('[Middleware] Dispatching', action);
            const result = next(action);        //将action 传入 reducer
            console.log('[Middleware] next state', store.getState())
            return result;
        }
    }
}

const composeEnhancers =  window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__|| compose; 
//配合redux extension

const store = createStore(rootReducer, composeEnhancers(applyMiddleware(logger)));

ReactDOM.render(<Provider store={store}><App /></Provider>, document.getElementById('root'));
registerServiceWorker();

将action变为actionCreators:方便进行异步操作

actions.js

export const INCREMENT = 'INCREMENT';
export const DECREMENT = 'DECREMENT';
export const ADD = 'ADD';
export const SUBTRACT = 'SUBTRACT';
export const STORE_RESULT = 'STORE_RESULT';
export const DELETE_RESULT = 'DELETE_RESULT';


//用action creater 创建 action
export const increment=()=>{        //返回一个obj
    return { 
        type:INCREMENT
    };
};

//action creater作为一个function 返回一个obj
export const decrement=()=>{
    return {
        type:DECREMENT
    };
};

export const add =(val)=>{
    return {
        type:ADD,
        val:val
    };
};

export const subtract=(val)=>{
    return{
        type:SUBTRACT,
        val:val
    };
};

export const store_result=(result)=>{
    return{
        type:STORE_RESULT,
        result:result
    };
};

export const delete_result=(id)=>{
    return{
        type:DELETE_RESULT,
        resultElId: id
    };
};

counter.js,对上述进行调用

import * as actionCreators from '../../store/actions/actions';
const mapDispatchToProps = dispatch => {
    return {
        onIncrementCounter: () => dispatch(actionCreators.increment()),
        onDecrementCounter: () => dispatch(actionCreators.decrement()),
        onAddCounter: () => dispatch(actionCreators.add(10)),
        onSubtractCounter: () => dispatch(actionCreators.subtract(15)),
        onStoreResult: (result) => dispatch(actionCreators.store_result(result)),
        onDeleteResult: (id) => dispatch(actionCreators.delete_result(id))
    }
};

Middleware-Redux thunk

https://github.com/reduxjs/redux-thunk

npm install --save redux-thunk

跟随教程,引入applymiddleware,放入state中;

import { createStore, combineReducers, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk'; //引入middleware

在middleware中第二个参数传入thunk;

const store = createStore(rootReducer, composeEnhancers(applyMiddleware(logger,thunk)));

利用middleware使用异步操作

在dispatch中传入的函数,调用一个异步函数,执行dispatch操作;

export const saveResult = (res)=>{
    return{
        type:STORE_RESULT,
        result:res
    };
};
//action creator 不返回一个action,而返回一个function——用于dispatch action
//故返回的function与action creator 中的内容是异步的

//返回一个dispatch——> 进行异步操作——两秒后调用saveResult
export const store_result=(result)=>{
    return dispatch=>{      //从middleware中得到dispatch
        setTimeout(() => {
            dispatch(saveResult(result));
        }, 2000);
    };
};

将actionCreator拆分+合并

actionType.js

export const INCREMENT = 'INCREMENT';
export const DECREMENT = 'DECREMENT';
export const ADD = 'ADD';
export const SUBTRACT = 'SUBTRACT';
export const STORE_RESULT = 'STORE_RESULT';
export const DELETE_RESULT = 'DELETE_RESULT';

counter.js

import * as actionTypes from './actionsType';

//用action creater 创建 action
export const increment=()=>{        //返回一个obj
    return { 
        type:actionTypes.INCREMENT
    };
};

//action creater作为一个function 返回一个obj
export const decrement=()=>{
    return {
        type:actionTypes.DECREMENT
    };
};

export const add =(val)=>{
    return {
        type:actionTypes.ADD,
        val:val
    };
};

export const subtract=(val)=>{
    return{
        type:actionTypes.SUBTRACT,
        val:val
    };
};

result.js

import * as actionTypes from './actionsType';

export const saveResult = (res)=>{
    return{
        type:actionTypes.STORE_RESULT,
        result:res
    };
};


//action creator 不返回一个action,而返回一个function——用于dispatch action
//故返回的function与action creator 中的内容是异步的

//返回一个dispatch——> 进行异步操作——两秒后调用saveResult
export const store_result=(result)=>{
    return dispatch=>{      //从middleware中得到dispatch
        setTimeout(() => {
            dispatch(saveResult(result));
        }, 2000);
    };
};

export const delete_result=(id)=>{
    return{
        type:actionTypes.DELETE_RESULT,
        resultElId: id
    };
};

index.js

export {
    add,
    subtract,
    increment,
    decrement
} from './counter';

export {
    store_result,
    delete_result
} from './result';


//将所有文件要export的都放入这儿,方便后面调用

需要import的js都从index中import即可;

异步获取数据后在reduce前改变数据

在action中改变data

export const saveResult = (res)=>{
    const updatedResult = res *2;
    return{
        type:actionTypes.STORE_RESULT,
        result:updatedResult
    };
};

在reducer中改变data

        case actionTypes.STORE_RESULT:
            return {
                ...state,
                results: state.results.concat({id: new Date(), value: action.result*2}) //可在这里处理res
            }

调用异步时,可传入getState获取当前state

export const store_result=(result)=>{
    return (dispatch, getState)=>{      //从middleware中得到dispatch
                    //getstate得到当前state
        setTimeout(() => {
            const oldCounter = getState().ctr.counter;
            console.log(oldCounter);
            dispatch(saveResult(result));
        }, 2000);
    };
};

优化代码——Utility Functions

reducer中调用return时,将return的obj内容用一个函数返回;
utility.js

export const updateObject = (oldObject, updatedValues)=>{
    return {
        ...oldObject,
        ...updatedValues      //需要更新的obj参数
    }
};

reducer

import * as actionTypes from '../actions/actionsType';
import {updateObject} from '../utility';
const initialState = {
    counter: 0
};

const reducer = ( state = initialState, action ) => {
    switch ( action.type ) {
        case actionTypes.INCREMENT:
            return updateObject(state,{counter: state.counter + 1});
        case actionTypes.DECREMENT:
            return updateObject(state,{counter: state.counter - 1});
        case actionTypes.ADD:
            return updateObject(state,{counter: state.counter + action.val})
        case actionTypes.SUBTRACT:
            return updateObject(state,{counter:state.counter - action.val});
    }
    return state;
};

export default reducer;
import * as actionTypes from '../actions/actionsType';
import {updateObject} from '../utility';

const initialState = {
    results: []
};

const reducer = ( state = initialState, action ) => {
    switch ( action.type ) {
        case actionTypes.STORE_RESULT:
            return updateObject(state,{results: state.results.concat({id: new Date(), value: action.result})});

        case actionTypes.DELETE_RESULT:
            const updatedArray = state.results.filter(result => result.id !== action.resultElId);
            return updateObject(state,{results: updatedArray});
    }
    return state;
};

export default reducer;

再细一点

import * as actionTypes from '../actions/actionsType';
import {updateObject} from '../utility';

const initialState = {
    results: []
};

const deleteResult=(state, action)=>{
    const updatedArray = state.results.filter(result => result.id !== action.resultElId);
    return updateObject(state,{results: updatedArray});
};

const reducer = ( state = initialState, action ) => {
    switch ( action.type ) {
        case actionTypes.STORE_RESULT:  return updateObject(state,{results: state.results.concat({id: new Date(), value: action.result})});
        case actionTypes.DELETE_RESULT: return deleteResult(state,action);
    }
    return state;
};

export default reducer;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值