[React] 13 - React-redux
什么情况下需要使用redux
-
某个组件的状态,需要让其他组件可以随时拿到(共享)。
-
一个组件需要改变另一个组件的状态(通信)。
-
总体原则:能不用就不用, 如果不用比较吃力才考虑使用。
React Components中的状态 --> 转移到redux那里。所以,状态的改变,地儿变了,让redux 代理去做。
Action就是个包含两个属性的object。
Store不干活,但调度。
Reducers掌管:初始化 state and 更新 state。
逐步分解
纯 react 版本
$create-react-app redux_test
思路:写了一个组件,其中定义了一个state。若干方法对该state进行算数操作。
... state = {count:0} //加法 increment = ()=>{ const {value} = this.selectNumber const {count} = this.state this.setState({count:count+value*1}) } //减法 decrement = ()=>{ const {value} = this.selectNumber const {count} = this.state this.setState({count:count-value*1}) } //奇数再加 incrementIfOdd = ()=>{ const {value} = this.selectNumber const {count} = this.state if(count % 2 !== 0){ this.setState({count:count+value*1}) } } //异步加 incrementAsync = ()=>{ const {value} = this.selectNumber const {count} = this.state setTimeout(()=>{ this.setState({count:count+value*1}) },500) } render() { ...
Redux 精简版
1)先写store,引入 countReducer。
//引入createStore,专门用于创建redux中最为核心的store对象 import {createStore} from 'redux' //引入为Count组件服务的reducer import countReducer from './count_reducer' //暴露store export default createStore(countReducer)
2)再创建countReducer,实现“动作改变状态”的各种switch流程定义。
const initState = 0 //初始化状态 export default function countReducer(preState=initState, action){ // console.log(preState); //从action对象中获取:type、data const {type, data} = action
//根据type决定如何加工数据 switch (type) { case 'increment': //如果是加 return preState + data case 'decrement': //若果是减 return preState - data default: return preState } }
3)再开始重新考虑组件,以下是“变化”。
变化3.1,state中的count转移到store管理,其他的部分则可以依然放在这里,例如carName。
state = {carName:'奔驰c63'}
变化3.2,发送 action,通过store 转发给 reducer去处理。(action 包含了 用于处理的所有信息:type and data)
increment = ()=>{ const {value} = this.selectNumber const {count} = this.state this.setState({count:count+value*1}) }
//加法 increment = ()=>{ const {value} = this.selectNumber store.dispatch({type:'increment', data:value*1}) // <-- 这种通过参数来控制 动作细节的 可能封装性不太好 }
本质:将state,以及 update state的部分,全都集中在 reducer去“实现”,而store的角色则是”调度“。
变化3.3,渲染时,状态只能从 store那里获得。
<h1>当前求和为:{store.getState()}</h1> // 这里是store的getState,而store里只管理保存了count,而非carName
store中state的任何变化,应该(但不是默认)触发 render。所以,需要如下一行代码在 index.js。
store.subscribe(()=>{ ReactDOM.render(<App/>,document.getElementById('root')) })
Redux 完整版
集中管理于一个文件。
// count_action.js
/*
该文件专门为Count组件生成action对象
*/
import {INCREMENT,DECREMENT} from './constant'
export const createIncrementAction = data => ({type:INCREMENT, data})
export const createDecrementAction = data => ({type:DECREMENT, data})
只是简单地 replaced by functions for 体现redux 的流程图,还有其他的好处么?
// index.js
import React, { Component } from 'react' // 引入store,用于获取redux中保存状态 import store from '../../redux/store' // 引入actionCreator,专门用于创建action对象 import {createIncrementAction,createDecrementAction} from '../../redux/count_action' export default class Count extends Component { state = {carName:'奔驰c63'} /* componentDidMount(){ //检测redux中状态的变化,只要变化,就调用render store.subscribe(()=>{ this.setState({}) }) } */ // 加法 increment = ()=>{ const {value} = this.selectNumber store.dispatch( createIncrementAction(value*1) ) } 。。。 }