1.Redux 基本使用
yarn add redux@4
2.Redux 异步请求
yarn add redux-thunk
3.Redux 跨组件传值
yarn add react-redux
// store/index.js import {createStore,applyMiddleware} from 'redux' //它是一个 中间件,是没有办法直接进行注入的,所以应该调用一个方法,这个方法可以把这个中间件进行注入到store实例 import thunk from 'redux-thunk //createStore(reducer:Reducer,enhancer?:StoreEnhancer):Store //createStore方法接受一个Reducer纯函数 //这个方法执行以后会得到一个Store对象 import reducer from './reducer' //需要对store对象进行增强,然后可以实现异步action //applyMiddleware(middleware1:Middleware):StoreEnhancer //这个方法接受一个中间件,返回一个store增强器 const thunEnhancer = applyMiddleware(thunk) const store= createStore(reducer,thunEnhancer) //这个store对象必须唯一,所以它必须在最底层进行注入 export default store
2,type.js -- 定义参数类型
//定义执行增加reducer的type数据 ('唯一数据类型') export const ADD_ACTION = Symbol('ADD_ACTION') export const MUNIS_ACTION = Symbol('MUNIS_ACTION') export const ASYNC_ACTION = Symbol('ASYNC_ACTION')
3.reducer
// store/reducer/index.js import {ADD_ACTION,ASYNC_ACTION,MUNIS_ACTION} from "../types" //初始化用户数据 const initState ={ count:100, value:[{a:[{}]}] } //定义一个reducer函数 //Action<T = any>{type:T} action对象中必须包含一个type属性 function reducer(state = initState,action){ console.log('------------ reducer') console.log(action) let newState = JSON,parse(JSON.stringify(state)) //string constant =>字符串常量,在编排的时候,常量常常单独定义,名字都是大写字母,单词之间使用_连接 //所以action.type应该要独立定义 switch (action.type){ // case'add': case ADD_ACTION: newState.count += action.step return newState case MUNIS_ACTION: newState.count -= action.step return newState case ASYNC_ACTION: newState.count += action.step return newState default: return newState } } export default reducer
3.action
import {ADD_ACTION,MUNIS_ACTION,ASYNC_ACTION} from "../types"; export function getAddAct(step){ return {type:ADD_ACTION,step} } export function getMunisAct(step){ return {type:MUNIS_ACTION,step} } //action必须是一个普通对象 //获取你需要添加一个中间件到store的配置对象中 //例如:redux-thunk这个中间件 function getAsyncAct(step){ //异步action,要求返回一个函数,这个函数会以形参的形式,把dispatch方法进行传入 return async function(dispatch){ step = await asyncFunc(step) dispatch({type:ASYNC_ACTION,step}) } } export { getAsyncAct } //模拟异步的方法 function asyncFunc(step){ return new Promise(resolve=>{ console.log('------ 异步执行开始') setTimeout(function(){ //延时返回结果 console.log('--------- 异步执行结束') resolve(step * 2) },1000) }) }
在实例入口index.js
// index.js 实例入口文件 import React from 'react' import {render} from 'react-dom' import App from './pages' //引入store对象 import store from './store' //解决库组件传值 ,就是react的组件传值 import { Provider } from 'react-redux' render( //绑定store属性 <Provider store={store}> <App/> </Provider>, document.getElementById('root') )
label.js组件
import React,{Component} from 'react' import {connect} from 'react-redux' import './index.css' class Label extends Component{ state={ myCount:0 } //componentDidMount(){ // this.setState({ // myCount:this.props.getState().count //}) // this.props.subscribe(()=>{ // this.setState({ // myCount:this.props.getState().count })}) } render(){ console.log('-------- label component') console.log(this.props) return( //在react中class是一个关键字,而元素是一个JSX对象,所以React中的class是一个className这个属性 <span className='value'>{this.props.myCount}</span> ) } } //connect 第一个方法应该要接收一个函数,这个函数会有一个store.state形参,因为这样可以取到store.state中的数据 //connect():InferableComponentEnhancer<DispatchProp> //Component Enhancer => 增强后的组件 =>高阶组件 //返回一个带有props的一个高阶组件 //MapStateToPropsParam =(state:State) =>TStateProps //说明connect需要传递一个函数,这个函数会有一个store.state形参 const mapStateToProps = function(state){ //mapStateToProps() in Connect(Label) must return a plain object.Instead received undefined. return{ myCount:state.count } } const enhancer = connect(mapStateToProps) const NewLabel = enhancer(Label) export default NewLabel
组件页面导入store
import React,{Component} from 'react' import {getAddAct,getMunisAct,getAsyncAct} from '../../store/action' //在react-redux的高阶组件中,应该具备两个功能,第一个可以自动绑定dispatch方法,第二个功能可以自定义获取state中的那些数据 //为什么自定义获取state中的那些数据?减少无用的参数传递,需要那些数据就取那些数据 import {connect} from 'react-redux' import './index.css' //function getAddAct(step){ // return {type:'add',step} //} class Button extends Component{ render(){ console.log('--------- button') console.log(this.props) return( <span className='btn' onClick={ //this.props.dispatch.bind(null,{type:'add',step:6}) () =>{ let obj; if(this.props.children === '减少'){ obj = getMunisAct(2)}else if(this.props.children === '增加'){ obj = getAddAct(6)}else{ obj=getAsyncAct(12)} this.props.dispatch(obj) } }>{this.props.children}</span> ) } } //export default Button // 调用高阶组件得到一个新的组件 const NewButton = connect()(Button) export default NewButton