redux是一个专门用作状态管理的js库,不是react的插件库。它可用于react、angular、vue等项目,但基本与react配合使用。
redux的三个核心概念:
action
是一个普通的js对象,包含以下两个属性:type
:是一个必选属性,值是一个字符串,且必须唯一,它标识了动作类型。data
:是一个可选属性,值可以是任意类型。reducer
是一个纯函数,用于初始化状态、加工状态。加工状态时,将根据旧的state和action,返回一个新的state。store
将state、action、reduce联系在一起,它提供如下API,store.getState()
,获取state。store.dispatch(action)
,派发action。store.subscribe(callback)
,监听store中的state的变化。首先,npm install --save redux
,安装redux库。
然后,此次代码变更涉及的文件有:
import { createStore } from "redux";
import counterReducer from "./reducer.js";
export default createStore(counterReducer);
createStore()
,用于创建store对象。整个应用只有一个store对象。
const initState = 0
export default function reducer(preState=initState,action){
const {type,data} = action;
switch(type){
case "increment": return preState+Number(data);
case "decrement": return preState-Number(data);
default: return preState
}
}
reducer实质是一个函数,它接受两个参数:
preState
,即旧的状态数据。action
,即action对象。reducer将根据动作类型,即type
,决定如何加工数据。import React, { Component } from 'react'
import store from "../../redux/store.js";
export default class Counter extends Component {
componentDidMount(){
store.subscribe(() => {
this.setState({})
})
}
increment = () => {
const {value} = this.selectEl;
store.dispatch({
type:"increment",
data:Number(value)
})
}
decrement = () => {
const {value} = this.selectEl;
store.dispatch({
type:"decrement",
data:Number(value)
})
}
incrementOdd = () => {
const {value} = this.selectEl;
const count = store.getState();
if(count % 2 !== 0){
store.dispatch({
type:"increment",
data:Number(value)
})
}
}
incrementWait = () => {
const {value} = this.selectEl;
setTimeout(() => {
store.dispatch({
type:"increment",
data:Number(value)
})
},1000)
}
render() {
const {increment,decrement,incrementOdd,incrementWait} = this;
return (
<div>
<h2>当前求和为{store.getState()}</h2>
<select ref={c => this.selectEl = c}>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
<button onClick={incrementOdd}>和为奇数时加</button>
<button onClick={incrementWait}>等一等再加</button>
</div>
)
}
}
store.subscribe(()=>{callback})
将监听store中的state是否发生变化,如果state变化,将执行对应回调。本例中,一旦state发生变化,将调用this.setState({})
来实现页面的重新渲染。
求和案例(redux精简版v2)、 求和案例(redux精简版v1)的区别在于:store.subscribe()不放在Counter组件(Counter/index.jsx)里,而是放在入口文件index.js里。
此次变更涉及的文件有:
同上。
同上。
import React, { Component } from 'react'
import store from "../../redux/store.js";
export default class Counter extends Component {
increment = () => {
const {value} = this.selectEl;
store.dispatch({
type:"increment",
data:Number(value)
})
}
decrement = () => {
const {value} = this.selectEl;
store.dispatch({
type:"decrement",
data:Number(value)
})
}
incrementOdd = () => {
const {value} = this.selectEl;
const count = store.getState();
if(count % 2 !== 0){
store.dispatch({
type:"increment",
data:Number(value)
})
}
}
incrementWait = () => {
const {value} = this.selectEl;
setTimeout(() => {
store.dispatch({
type:"increment",
data:Number(value)
})
},1000)
}
render() {
const {increment,decrement,incrementOdd,incrementWait} = this;
return (
<div>
<h2>当前求和为{store.getState()}</h2>
<select ref={c => this.selectEl = c}>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
<button onClick={incrementOdd}>和为奇数时加</button>
<button onClick={incrementWait}>等一等再加</button>
</div>
)
}
}
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import store from "./redux/store.js";
ReactDOM.render( <App />,document.getElementById("root"));
store.subscribe(() => {
ReactDOM.render( <App />,document.getElementById("root"));
})
求和案例(纯react版本)