ReactJavaScript 进阶营

React.js学习笔记(14) React-router-re

2017-12-31  本文已影响73人  woow_wu7

(一) 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(
    <Provider store={store}>
        <ConnectedRouter history={history}>               // 使用ConnectedRouter 
            <App>
                <RouterA/>                     // 路由组件,在App中用{this.props.children}引入
            </App>
        </ConnectedRouter>
    </Provider>
, document.getElementById('root'));
registerServiceWorker();

redux截图







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

作用: 实时更新的reducer

(1) replaceReducer(nextReducer)

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

(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 (
            <div>
                <Username {...this.props}></Username>
            </div>
        )
    }
}
function mapStateToProps(state) {
    return {
        name: state.username.username
    }
}
function mapDispatchToProps(dispatch) {
    return bindActionCreators(actionTotal,dispatch)
}
export default connect(mapStateToProps,mapDispatchToProps)(usernameContainer)

injectAsyncReducer函数效果图







(三) redux-thunk中间件

作用: dispatch一个函数

(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 (
            <div>
                <Username {...this.props}></Username>
            </div>
        )
    }
}
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 (
            <div key={key}>
                <img src={item.image_url} alt=""/> 
            </div>
        )
    }
    render() {
        // console.log(this.props.imageUrl,'this.props.imageUrl');
        return (
            <div>
               主页
                <div onClick={this.getI}>
                    点击获得图片
                </div>
                <br/>
                <br/>
                {
                     this.props.imageUrl && this.props.imageUrl.map(this.goG)
                }
            </div>
        )
    }
}

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
上一篇下一篇

猜你喜欢

热点阅读