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={{ 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);