React.js学习笔记(14) React-router-redux中间件 + ( Redux-thunk中间件 ) + ( injectAsyncReducer函数 )

(一) react-router-redux中间件

所需环境:

(1) 用creact-react-app脚手架启一个new项目
create-react-app new

(2)安装redux
cnpm install redux --save-dev

(3)安装react-redux
cnpm install react-redux --save-dev

(4)安装redux-devtools
cnpm install redux-devtools --save-dev

(5)安装react-router-dom
cnpm install react-router-dom --save-dev

(1) 安装react-router-redux

react-router-redux作用:可以把router中的location(url信息等)注入到redux中,用redux来统一管理


cnpm install react-router-redux@next --save-dev




一般会用到react-router-redux中的:

ConnectedRouter , routerReducer , routerMiddleware , push 

// 这里要注意,ConnectedRouter的首字母要大写 

// 注意是安装( @next版本 )

// 在两个地方会用到react-router-redux

1. 在store.js   用到routerReducer,routerMiddleware
2. 在index.js   用到ConnectedRouter

(2) 安装 history 库

history是一个JavaScript库,可让您轻松管理任何运行JavaScript的会话历史记录。用来管理历史堆栈,导航,确认导航以及在会话之间保持状态。


cnpm install history --save-dev

(2) 新建 history.js


import createHistory from 'history/createBrowserHistory';

export default createHistory();



history.js在两个地方会用到:

1.store.js 中

2.入口文件js中 (index.js)

(3) store.js


import {createStore, combineReducers, applyMiddleware} from 'redux';
import { routerReducer, routerMiddleware} from 'react-router-redux';
import username from '../component/username/reducer';
import history from  '../history/history';               // 上面的history.js
import thunkMiddleware from 'redux-thunk';               // redux-thunk中间件用于dispatch一个函数

const totalReducer = {
    username:username,
    router:routerReducer                                          // routerReducer        
}

export const store = createStore(                                 // 根据规则建立store
    combineReducers({                                             // combineReducers组合多个reducer
        ...totalReducer
    }),
    window.devToolsExtension ? window.devToolsExtension() : undefined, // devTools插件
    applyMiddleware(thunkMiddleware,routerMiddleware(history))     // routerMiddleware
);


export function injectAsyncReducer(name, reducer) {   // 异步注入reducer
    store.AsyncReducers = store.AsyncReducers || {};
    if (store.AsyncReducers[name]) {
        return ;
    }
    store.AsyncReducers[name] = reducer;
    store.replaceReducer(combineReducers({   // store的api中的replaceReducer(nextReducer)方法
        ...totalReducer,
        ... store.AsyncReducers
    }))
}

(4) index.js入口文件


import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import {Provider} from 'react-redux';            //Provider的作用是保存store给子组件中的connect使用
import RouterA from './router/router';
// import {BrowserRouter} from 'react-router-dom';
import {ConnectedRouter} from 'react-router-redux';        // 引入ConnectedRouter
import history from './history/history';

import {store} from './store/store';
ReactDOM.render(
    
                       // 使用ConnectedRouter 
            
                                     // 路由组件,在App中用{this.props.children}引入
            
        
    
, document.getElementById('root'));
registerServiceWorker();

React.js学习笔记(14) React-router-redux中间件 + ( Redux-thunk中间件 ) + ( injectAsyncReducer函数 )_第1张图片
redux截图








(二) injectAsyncReducer函数 (名字是自己定义的)

作用: 实时更新的reducer

(1) replaceReducer(nextReducer)

replaceReducer(nextReducer)是redux的api中的 store 的一个函数

  • 作用:替换 store 当前用来计算 state 的 reducer。
    这是一个高级 API。只有在你需要实现代码分隔,而且需要立即加载一些 reducer 的时候才可能会用到它。在实现 Redux 热加载机制的时候也可能会用到。
  • ( 我的理解是: 实时更新的reducer )
  • (redux中文文档)http://www.redux.org.cn/docs/api/Store.html#replaceReducer

(2) injectAsyncReducer函数定义

store.js中


export function injectAsyncReducer(name, reducer) {     // name, reducer作为参数
    store.AsyncReducers = store.AsyncReducers || {};    // 存在赋值,不存在赋值空对象
    if (store.AsyncReducers[name]) {      // store中的AsyncReducers对象存在name属性,就返回
        return ;
    }
    store.AsyncReducers[name] = reducer;   // 不存在name属性,就赋值给name属性
    store.replaceReducer(combineReducers({  // 用replaceReducer函数获得时时更新的reducer
        ...totalReducer, 
        ... store.AsyncReducers  // 拿到AsyncReducers对象,给combineReducers
    }))
}


(2) injectAsyncReducer函数使用

container.js中


import React,{Component} from 'react';
import Username from './username';
import {bindActionCreators}  from 'redux';
import * as actionTotal from './action';
import {connect} from 'react-redux';

import {injectAsyncReducer} from '../../store/store';                    // 引入
injectAsyncReducer('address',require('./reducer').default);              // 使用

class usernameContainer extends Component {
    render() {
        return (
            
) } } function mapStateToProps(state) { return { name: state.username.username } } function mapDispatchToProps(dispatch) { return bindActionCreators(actionTotal,dispatch) } export default connect(mapStateToProps,mapDispatchToProps)(usernameContainer)
React.js学习笔记(14) React-router-redux中间件 + ( Redux-thunk中间件 ) + ( injectAsyncReducer函数 )_第2张图片
injectAsyncReducer函数效果图








(三) redux-thunk中间件

作用: dispatch一个函数

  • redux-thunk 支持 dispatch function,以此让 action creator 控制反转。被 dispatch 的 function 会接收 dispatch 作为参数,并且可以异步调用它。这类的 function 就称为 thunk。

(1) 安装

cnpm install redux-thunk --save-dev

(2) 引入



import {createStore, combineReducers, applyMiddleware} from 'redux';
import username from '../component/username/reducer';
import { routerReducer, routerMiddleware} from 'react-router-redux';
import history from  '../history/history';
import thunkMiddleware from 'redux-thunk';                                  // 引入

const totalReducer = {
    username:username,
    router:routerReducer
}

export const store = createStore(
    combineReducers({
        ...totalReducer
    }),
    window.devToolsExtension ? window.devToolsExtension() : undefined,
    applyMiddleware(thunkMiddleware,routerMiddleware(history))             // 使用
);



(3) 使用

action.js



export function getImage() {
    return dispatch => {      // return 一个函数,dispatch函数作为参数
        const p = fetch('http://image.baidu.com/channel/listjson?pn=0&rn=30&tag1=%E7%BE%8E%E5%A5%B3&tag2=%E5%85%A8%E9%83%A8&ie=utf8',{
            method:'GET'
        }).then(result => result.json() );

        p.then(result => {
            console.log(result,'result');
            dispatch({      // dispatch一个action
                type: actionTypes.GET_IMAGE,
                payload: result
            })
        })
        
        return p;
    }
}




------------------------------------------------------------------------------------
reducer.js


import actionTypes from './constant';

const initialState = {
    username:{
        username: '重庆'
    },
    image:{}
}


export default function reducerA(state=initialState,action) {
    switch(action.type) {
        case actionTypes.GET_IMAGE:
            return {
                ...state,
                image:action.payload
            }    
        default:
            return state;
    }

}




------------------------------------------------------------------------------------
container.js



import React,{Component} from 'react';
import Username from './username';
import {bindActionCreators}  from 'redux';
import * as actionTotal from './action';
import {connect} from 'react-redux';

import {injectAsyncReducer} from '../../store/store';
injectAsyncReducer('address',require('./reducer').default);

class usernameContainer extends Component {
    render() {
        return (
            
) } } function mapStateToProps(state) { return { name: state.username.username, imageUrl:state.address.image.dat // 拿到state.address.image.data命名为imageUrl,传给username.js } } function mapDispatchToProps(dispatch) { return bindActionCreators(actionTotal,dispatch) } export default connect(mapStateToProps,mapDispatchToProps)(usernameContainer) ------------------------------------------------------------------------------------ username.js import React,{Component} from 'react'; export default class username extends Component { getI = () => { this.props.getImage(); } goG = (item,key) => { return (
) } render() { // console.log(this.props.imageUrl,'this.props.imageUrl'); return (
主页
点击获得图片


{ this.props.imageUrl && this.props.imageUrl.map(this.goG) }
) } }

React.js学习笔记(14) React-router-redux中间件 + ( Redux-thunk中间件 ) + ( injectAsyncReducer函数 )_第3张图片
redux.thunk效果图

参考文档:
(1) react-router-redux
https://github.com/ReactTraining/react-router/tree/master/packages/react-router-redux
(2)react-router v4 使用 history 控制路由跳转
https://segmentfault.com/a/1190000011137828
(3) redux-thunk
https://github.com/gaearon/redux-thunk

你可能感兴趣的:(React.js学习笔记(14) React-router-redux中间件 + ( Redux-thunk中间件 ) + ( injectAsyncReducer函数 ))