Redux 是 JavaScript 应用的状态容器,提供可预测的状态管理。
当一个项目的组件很多,且多个组件需要共享一个状态,即多交互、多数据源,如
某个组件的状态,需要其他组件共享;某个状态需要在任何组件都可以拿到;一个组件需要改变全局状态;一个组件需要改变另一个组件的状态等,此时可以考虑使用Redux。
基本使用
redux的主要组成部分就不说了,直接通过实例讲在redux在react项目的使用。
1、安装redux
npm install -S redux
2、新建一个文件夹,命名为store,在里面新建一个index.js(初步代码)
3、创建Reducer,在store文件夹下新建reducer.js,此时设置两个state,分别为num,age
//改变数量
const changeNumber = function (state = { num: 0 }, action) {
switch (action.type) {
case 'Add':
return {
num:state.num + 1
}
case 'Minus':
return {
num:state.num - 1
}
default:
return state
}
}
//改变年龄
const changeAge = function (state = { age: 0 }, action) {
switch (action.type) {
case 'ageAdd':
return {
age:state.age + 1
}
case 'ageMinus':
return {
age:state.age - 1
}
default:
return state
}
}
4、合并Reducer(该步骤不是必须,当状态过多,分模块时可以考虑使用)
import { combineReducers } from "redux"
//合并Reducer
const rootReducer = combineReducers({
number:changeNumber,
age:changeAge
})
即当前的reducer.js
import { combineReducers } from "redux"
//改变数量
const changeNumber = function (state = { num: 0 }, action) {
switch (action.type) {
case 'Add':
return {
num:state.num + 1
}
case 'Minus':
return {
num:state.num - 1
}
default:
return state
}
}
//改变年龄
const changeAge = function (state = { age: 0 }, action) {
switch (action.type) {
case 'ageAdd':
return {
age:state.age + 1
}
case 'ageMinus':
return {
age:state.age - 1
}
default:
return state
}
}
//合并Reducer
const rootReducer = combineReducers({
number:changeNumber,
age:changeAge
})
export default rootReducer
5、创建store,即index.js
import { createStore } from "redux";
import rootReducer from "./reducer";
const store = createStore(rootReducer)
export default store
此时的目录结构 store->index.js、reducer.js
6、使用store.getState()获取store状态state
创建一个组件One.js
import React from 'react';
import { Button } from 'element-react';
import store from '../store';
class One extends React.Component {
constructor(props) {
super(props);
this.state = {
msg:''
}
}
componentDidMount(){
console.log(store.getState(),'store----') //在挂载完成控制台打印
}
render(){
return (
<div style={{backgroundColor:'#13ce66',padding:'10px',width:'200px',margin:'auto',marginTop:'20px'}}>
<p>组件一</p>
</div>
)
}
}
export default One
打印信息如下,通过store.getState()能拿到state的值(未修改时为默认值)
让其在页面显示
import React from 'react';
import { Button } from 'element-react';
import store from '../store';
class One extends React.Component {
constructor(props) {
super(props);
this.state = {
number:''
}
}
componentDidMount(){
console.log(store.getState(),'store----')
this.setState({
number:store.getState().number.num //修改当前组件number的状态
})
}
render(){
return (
<div style={{backgroundColor:'#13ce66',padding:'10px',width:'200px',margin:'auto',marginTop:'20px'}}>
<p>组件一</p>
<span>数量:{this.state.number}</span>
</div>
)
}
}
export default One
7、使用store.dispatch()修改状态state
再次修改One.js组件,添加按钮,点击修改store中的number,数量+1 数量-1
import React from 'react';
import { Button } from 'element-react';
import store from '../store';
class One extends React.Component {
constructor(props) {
super(props);
this.state = {
number:''
}
this.addNumber = this.addNumber.bind(this)
this.minusNumber = this.minusNumber.bind(this)
}
addNumber(){ //数量+1
store.dispatch({
type:'Add',
payload:{}
})
console.log(store.getState().number,'add----')
}
minusNumber(){ //数量-1
store.dispatch({
type:'Minus',
payload:{}
})
console.log(store.getState().number,'minus----')
}
componentDidMount(){
console.log(store.getState(),'store----')
this.setState({
number:store.getState().number.num
})
}
render(){
return (
<div style={{backgroundColor:'#13ce66',padding:'10px',width:'200px',margin:'auto',marginTop:'20px'}}>
<p>组件一</p>
<span>数量:{this.state.number}</span>
<div>
<Button onClick={this.addNumber}>数量+1</Button>
<Button onClick={this.minusNumber}>数量-1</Button>
</div>
</div>
)
}
}
export default One
点击页面“数量+1”按钮,控制台查看输出结果,此时store中的number已经+1变成1
然后点击“数量-1”按钮,number结果-1变成0
8、设置监听函数store.subscribe()
为了让页面的某个状态随着store的变化实时改变,设置监听函数(挂载结束后),监听store中state的变化,执行相应的方法,更新本组件的state值。
import React from 'react';
import { Button } from 'element-react';
import store from '../store';
class One extends React.Component {
constructor(props) {
super(props);
this.state = {
number:store.getState().number.num //初始值
}
this.addNumber = this.addNumber.bind(this)
this.minusNumber = this.minusNumber.bind(this)
this.storeStateChange = this.storeStateChange.bind(this)
}
addNumber(){ //数量+1
store.dispatch({
type:'Add',
payload:{}
})
console.log(store.getState().number,'add----')
}
minusNumber(){ //数量-1
store.dispatch({
type:'Minus',
payload:{}
})
console.log(store.getState().number,'minus----')
}
storeStateChange(){ //store中state状态改变,触发此方法,重新设置该组件的state值
this.setState({
number:store.getState().number.num
})
}
componentDidMount(){
console.log(store.getState(),'store----')
store.subscribe(this.storeStateChange) //监听store,过store中状态改变,执行相应的方法
}
render(){
return (
<div style={{backgroundColor:'#13ce66',padding:'10px',width:'200px',margin:'auto',marginTop:'20px'}}>
<p>组件一</p>
<span>数量:{this.state.number}</span>
<div>
<Button onClick={this.addNumber}>数量+1</Button>
<Button onClick={this.minusNumber}>数量-1</Button>
</div>
</div>
)
}
}
export default One
这个时候点击按钮,页面的显示的数量也会随着变化。至此,整个流程打通了。
进阶:多组件场景下,引入store,获取值、修改值的方式一致,当多个组件共享一个state时,某个组件修改store中的state,另外的组件获取到的state也将相应变化,反之亦然。
具体细节及原理请前往官网学习
Redux 中文官网 - JavaScript 应用的状态容器,提供可预测的状态管理。 | Redux 中文官网http://cn.redux.js.org/
对比Vue中的状态管理器Vuex,你会发现些许相似之处: