react-redux的使用

https://www.jianshu.com/p/7a6708cde333

安装:yarn add redux  react-redux --save

redux分为三个部分组成action  reducer  store

action可以触发reducer中的state   在改变共享状态的文件处使用

const { dispatch } = this.props;   //使用connect后会生成dispatch

dispatch(switchMenu(title));

export const type = {
    SWITCH_MEUN: 'SWITCH_MEUN'
}

export function switchMenu(menuName) {
    console.log('menuName',menuName)
    return { // 这个返回的就是reducer中的action
        type:type.SWITCH_MEUN,
        menuName: menuName
    }
}

 

reducer是放置与改变共享状态值的地方 

 Reducer是生成store的方法createStore的参数,Reducer是一个方法,它接收两个参数state和action 

state即当前组件间共享的数据,acion = {动作类别type,动作参数name}

import { type } from '../action';
const initialState = {
    menuName: '首页'
}

export default (state = initialState,action)=>{
    console.log('action',action) // 使用dispatch调用action中的方法会触发更新state 获取到action之后根据type的不同来更改不同的值    类似于action:{type: "SWITCH_MEUN", menuName: "订单管理"}
    switch (action.type) {
        case type.SWITCH_MEUN:
            return {
                ...state, // 保存上一个状态值的写法
                menuName:action.menuName
            }
            break;
        default:
            return {...state}
            break

    }
}

 store.js

// createStore是一个工厂方法,内里通过返回出去的方法作用于连保持了state(state就是共享数据)的生命
// 并返回了一个包括三个方法的对象,三个方法分别为getState,subscribe,dispatch
// getState即获取当前state也就是共享数据
// subscribe接收一个方法为参数,目的是注册这个方法为dispatch调用后的callback方法
// dispatch接收一个参数,这个参数是action = {动作类别, 动作参数}
// dispatch内部调用了Reducer并在Reducer执行完毕后执行subscribe注册的callback(一般用于更新组件渲染)
import { createStore } from "redux";
import reducer from './../reducer';
const configureStore=()=>createStore(reducer) //没有用大括号包着的代表返回的意思  Reducer传入craeteStore生成store
export default configureStore //没有用大括号包着的代表返回的意思

在根节点处引入store

import React from 'react';
import ReactDOM from 'react-dom';
import './public/css/index.css'
import Route from './route'
import { Provider } from 'react-redux'
import configureStore from './redux/store/index.js';
import * as serviceWorker from './public/js/serviceWorker';
const store = configureStore(); //保存数据源的地方
ReactDOM.render(
    // Provider是提供数据源的地方 Provider将所有要共享数据的组件共同的父组件包裹起来
    //     并作为含有context的高阶组件,同时将store传入,作为context共享的内容
    <Provider store={store}>
        <Route />
    </Provider>
   , document.getElementById('root'));

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

使用共享状态的文件的使用

import React from 'react'
import {Row, Col} from 'antd'
import '@/components/Header/index.less'
import Unit from '../../unit/index'
import Axios from '../../axios/index'
import { connect } from "react-redux";

class Header extends React.Component{
    constructor(props) {
        super(props)
        this.state = {
            systime : '',
            weather: '晴转多云',
            weather_pic: ''
        }
    }
    componentWillMount() {
        setInterval(()=>{
            let systime = Unit.formatetime(new Date().getTime())
            this.setState({
                systime: systime
            })
        },1000)
       Axios.jsonp({url:'http://api.map.baidu.com/telematics/v3/weather?location=chengdu&output=json&ak=3p49MVra6urFRGOT9s8UBWr2'})
       .then((res)=>{
           this.setState({
               weather: res.results[0].weather_data[0].weather,
               weather_pic: res.results[0].weather_data[0].dayPictureUrl
           })
       }).catch((err)=>{
           console.log(err)
       })
        //  JsonP('http://api.map.baidu.com/telematics/v3/weather?location=chengdu&output=json&ak=3p49MVra6urFRGOT9s8UBWr2',{},function(err,data){
        //     console.log(data)
        // })
    }
    render() {
        return(
            <div className="header">
                <Row className="header-top">
                    <Col span={24}>
                        <span>cjz管理后台</span>
                        <span href="#">退出</span>
                    </Col>
                </Row>
                <Row className="header-bottom">
                    <Col span={4} className="header-bottom-left">
                        <span>{this.props.menuName} </span>
                    </Col>
                    <Col span={20} className="header-bottom-right">
                        <span className="detail-time">{this.state.systime}</span>
                        <img className="weather-pic" src={this.state.weather_pic} alt=""/>
                        <span className="weather-detail">{this.state.weather}</span>
                    </Col>
                </Row>
            </div>
        )
    }
}
const mapStateToProps = state => { //每个共享数据的组件都要通过mapStateToProps方法将state映射成自己可接收的props对象,之后通过this.props.menuName直接使用state中的值
    return {
        menuName: state.menuName
    }
};
export default connect(mapStateToProps)(Header); //第一个是接受回调方法  使用connect包裹Header组件

改变共享状态的文件

import React from 'react';
import { Menu} from 'antd';
import MeunList from '../../resource/navdata';
import { connect } from "react-redux";
import { switchMenu } from "../../redux/action";
import '@/components/NavLeft/index.less';
import { HashRouter, Link } from "react-router-dom";
const { SubMenu } = Menu;
class NavLeft extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            MenuNode: '',
            currentKey: ''
        }
    }
    componentWillMount() {
        const nodeTree = this.renderMenu(MeunList)
        var routeKey = window.location.hash.substr(1);
        this.setState({
            MenuNode: nodeTree
        })
    }
    renderMenu = (data) => {
        return data.map((item) => {
            if (item.children) {
                return (
                    <SubMenu key={item.key} title={item.title}>
                       {this.renderMenu(item.children)}
                    </SubMenu>
                )
            }
            return (
                <Menu.Item key={item.key}> <Link to={item.key}>{item.title}</Link></Menu.Item>
            )
        })
    }

    handleClick = ({ item, key }) => {
        var title = item.props.children[1].props.children
        // 事件派发,自动调用reducer,通过reducer保存到store对象中
        const { dispatch } = this.props; //使用connect后会生成dispatch
        dispatch(switchMenu(title)); //使用dispatch调用action文件中的方法后会触发reducer中的方法,最终改变共享状态

    };
    render() {
        return (
            <HashRouter>
                <div className="left-bar">
                    <div className="logo">Logo</div>
                    <div className="nav"></div>
                    <Menu theme='dark' onClick={this.handleClick} style={{ width: 256 }} mode="vertical">
                        {this.state.MenuNode}
                    </Menu>

                </div>
            </HashRouter>
        )
    }
}
export default connect()(NavLeft);

 如果需要异步修改状态值则需要安装thunk包 (此处为新增的内容)npm install redux-thunk redux-logger --save 

定义的状态页面store.js

import {createStore, applyMiddleware} from "redux"; // 引入中间件
import logger from 'redux-logger' // 刚才新增的依赖
import thunk from 'redux-thunk'
const counterReducer = (state = 0, action) =>{
    switch (action.type) {
        case 'add':
            return state + 1
        case 'mines':
            return state - 1
        default:
            return state
    }
}
const store = createStore(counterReducer, applyMiddleware(logger, thunk)) // 这样就可以异步执行action修改值
export default store;

具体使用页面 page.js

import React, {Component} from 'react';
import {connect} from 'react-redux'

class ReactReduxPage extends Component {
    constructor(props) {
        super(props);
    }
    render() {
        console.log(this.props)
        const {num, add, mines, asyAdd} = this.props
        return (
            <div>
                <h1>reactReduxPage</h1>
                <span>{num}</span>
                <button onClick={() => add()}>+</button>
                <button onClick={() => mines()}>-</button>
                <button onClick={() => asyAdd()}>异步加</button>
            </div>
        );
    }
}
const mapStateToProps = state => { // 数据映射到props上
    return {
        num: state
    }
}
const mapDispatchToProps = { // 方法映射到props上
    add: () => {
        return {type: 'add'}
    },
    mines: () => {
        return {type: 'mines'}
    },
    asyAdd: () => dispatch => { // 异步修改数据
        setTimeout(() => {
            dispatch({type: 'add'})
        }, 1000)
    }
}
export default connect(mapStateToProps, mapDispatchToProps)(ReactReduxPage);

 

 
posted @ 2019-08-17 20:40  陈小作  阅读(201)  评论(0编辑  收藏  举报