1)redux是什么
- redux是一个专门用于做状态管理的JS库(不是react插件库)。
- 它可以用在react, angular, vue等项目中, 但基本与react配合使用。
- 作用: 集中式管理react应用中多个组件共享的状态。
2) 什么情况下需要使用redux
- 某个组件的状态,需要让其他组件可以随时拿到(共享)。
- 一个组件需要改变另一个组件的状态(通信)。
- 总体原则:能不用就不用, 如果不用比较吃力才考虑使用。
3) redux的工作流程
4)redux的三个核心概念
一:action
- 动作的对象
- 包含2个属性
- type:标识属性, 值为字符串, 唯一, 必要属性
- data:数据属性, 值类型任意, 可选属性
- 例子:{ type: ‘ADD_STUDENT’,data:{name: ‘tom’,age:18} }
二:reducer
- 用于初始化状态、加工状态。
- 加工时,根据旧的state和action, 产生新的state的纯函数。
三:store
- 将state、action、reducer联系在一起的对象
- 如何得到此对象?
- import {legacy_createStore as createStore} from ‘redux’
- import reducer from ‘./reducers’
- const store = createStore(reducer)
- 此对象的功能?
- getState(): 得到state
- dispatch(action): 分发action, 触发reducer调用, 产生新的state
- subscribe(listener): 注册监听, 当产生了新的state时, 自动调用
5)精简版的redux
首先
npm i 'redux'
src----->redux---->count_reducer.js
/*
该文件是用于创建一个为Count服务的reducer,reducer的本质就是一个函数
reducer函数会接到两个参数,分别会:之前的状态(preState) ,动作对象(action)
*/
const initState=0 //初始化状态
export default function countReducer(preState=initState,action){
// 从action对象中获取:type,data
const {
type,data}=action
// 根据type决定如何加工数据
switch (type) {
case 'increment'://如果是加
return preState+data
case 'decrement'://如果是减
return preState-data
case 'incrementIfOdd':
return preState+data
case 'incrementAsync':
return preState+data
default:
return preState
}
}
src----->redux---->store.js
/*
该文件专门用于暴露一个store对象,整个应用只有一个store对象
*/
// 引入createStore,专门用于创建redux最为核心的store对象
import {
legacy_createStore as createStore} from 'redux'
// 引入为count服务的reducer
import countReducer from './count_reducer'
// 暴露store
export default createStore(countReducer)
src----component—Count—index.jsx(需使用store中的状态,需引入store)
- 读取数据:store.getState()
- 监测redux中状态的变化,只要变化,就调用render:
store.subscribe(()=>{
this.setState({})
}) - 分发action, 触发reducer调用, 产生新的state(此处的type要和count_reducer.js中声明的type命名一致)
store.dispatch({type:‘increment’,data:value*1})
import React, {
Component } from 'react'
// 引入store,用于获取redux中保存的状态
import store from '../../redux/store'
export default class Count extends Component {
state={
carName:'奔驰c63'}
/* componentDidMount(){
// 监测redux中状态的变化,只要变化,就调用render
store.subscribe(()=>{
this.setState({})
})
} */
// 加法
increment=()=>{
const {
value}=this.selectNumber
// 通知redux加value
store.dispatch({
type:'increment',data:value*1})
}
// 减法
decrement=()=>{
const {
value}=this.selectNumber
store.dispatch({
type:'decrement',data:value*1})
}
// 奇数再加
incrementIfOdd=()=>{
const {
value}=this.selectNumber
const count=store.getState()
if (count%2!==0) {
store.dispatch({
type:'incrementIfOdd',data:value*1})
}
}
// 异步加
incrementAsync=()=>{
const {
value}=this.selectNumber
const count=store.getState()
setTimeout(()=>{
store.dispatch({
type:'incrementAsync',data:value*1})
},500)
}
render() {
return (
<div>
<h1>当前求和为:{
store.getState()}</h1>
<select ref={
c=>this.selectNumber=c} >
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button onClick={
this.increment}>+</button>
<button onClick={
this.decrement}>-</button>
<button onClick={
this.incrementIfOdd}>当前求和为奇数再加</button>
<button onClick={
this.incrementAsync}>异步加</button>
</div>
)
}
}
src---->index.js()
import React from "react";
import {
createRoot } from 'react-dom/client'; //react18的引入方式
import App from './App'
import store from './redux/store'
const root=createRoot(document.getElementById('root'))
root.render( < App />) //react18的渲染方式
// 监测redux中状态的变化,只要变化,就调用render
store.subscribe(()=>{
root.render( < App />)
})