redux配合react-redux使用
安装
npm install redux
npm install react-redux
在index.js下引入Provider,以及store
通过react-redux 提供的provider提供器 将全局状态对象挂载到根元素的上下文上
import {Provider} from 'react-redux'
import store from './ReactRedux/store/store'
ReactDOM.render(<Provider store={store}><App /></Provider>,
document.getElementById('root'));
actionType.js 存放状态值,一遍其他地方可以以变量的方式引用
避免项目复杂状态值较多的时候发生混乱
export const CHANGE_NAME = 'CHANGE_NAME'
export const CHANGE_AGE = 'CHANGE_AGE'
reducer.js
当全局状态值较复杂时可以新建一个js文件存放
import {CHANGE_NAME,CHANGE_AGE} from './actionType'
let state={
name:'樱吹雪',
age:16
}
export default (prevState=state,actions)=>{
let newData = JSON.parse(JSON.stringify(prevState))
/*
1. 修改引用类型数据的时候回导致修改源数据,导致新数据和老数据对比为真
2. 新数据老数据对比为真,页面不更新
*/
let {type,payload} = actions
switch (type) {
case CHANGE_NAME:
newData.name = payload
break;
case CHANGE_AGE:
newData.age = payload
break;
default:
break;
}
return newData
}
actionCreator.js不在发送action,单纯用来创造action
[CHANGE_NAME](){
let action = {
type:CHANGE_NAME,
payload:'赤染樱'
}
return action
},
[CHANGE_AGE](){
let action = {
type:CHANGE_AGE,
payload:500
}
return action
}
组件中使用全局状态值,
通过react-redux 提供的connect 从跟组件的上下文上获取store对象,
通过高阶组件将获得到的store传给目标组件的props
import React,{Component} from 'react'
import {connect} from 'react-redux'
import ActionCreator from './store/actionCreator'
import {bindActionCreators} from 'redux'
class Son2 extends Component{
render(){
let {name,age,CHANGE_AGE} = this.props
return(
<div>
<h3>son2</h3>
{name}{age}
<button onClick={CHANGE_AGE}>changeage</button>
</div>
)
}
}
export default connect(state=>state,
dispatch=>bindActionCreators(ActionCreator,dispatch))(Son2)
connect的本质是一个方法返回一个高阶组件
参数1 mapStateToProps 映射全局状态值到props里
参数2 mapDispatchToProps 映射方法到props里,不写默认映射dispatch,return什么映射什么
mapStateToProps
本质也是一个函数
- 该函数接收全局状态值作为参数
- 该函数返回的数据会被映射到组件的props里
let mapStateToProps = (state)=>{
console.log(state)
console.log('mapStateToProps')
return state
}
mapDisPatchToProps
本质也是一个函数
- 可以接dispatch 作为参数
- return的对象也会映射到props里
mapDispatchToProps 如果为空 将dispath 映射到props里
如果不为空 将return的对象映射到props里
let mapDispatchToProps = (dispatch) =>{
//将ActionCreator的方法映射到组件的props属性上
//当方法被调用时会自动执行一次dispatch
return bindActionCreators(ActionCreator,dispatch)
}
在抛出时可以简写为
export default connect(state=>state,
dispatch=>bindActionCreators(ActionCreator,dispatch))(组件名)
redux+react-redux的异步问题
在单独使用时,异步操作可以统一放到ActionCreator中,但结合使用后,ActionCreator的方法返回值必须是一个对象
解决方法
applyMiddleWare+redux-thunk解决异步的中间件
store.js
import {createStore,applyMiddleware} from 'redux'
import thunk from 'redux-thunk' //解决异步的插件 加起来异步中间件
import reducer from './reducer'
export default createStore(reducer,applyMiddleware(thunk))
ActionCreator.js中存放异步
[CHANGE_NAME](){
return (dispatch)=>{
setTimeout(()=>{
let action = {
type:CHANGE_NAME,
payload:'赤染樱'
}
dispatch(action)
},1000)
}
}
题外话,setState的特性
constructor(){
super()
this.state = {
num:1
}
}
componentDidMount(){
console.log(this.state.num)//1
this.setState({num:2})
console.log(this.state.num)//1
setTimeout(()=>{
this.setState({num:3})
console.log(this.state.num)//3
this.setState({num:4})
console.log(this.state.num)//4
},0)
console.log(this.state.num)//1
}
setState 是个异步
但是如果setState放到了异步中 就会变成同步