Redux
Redux是React最常用的集中状态管理工具,类似于pinia(vues),可以独立于框架运行。
作用:通过集中管理的方式管理应用的状态
使用步骤:
1.定义一个reduce函数(根据当前想要做的修改返回一个新的状态)
2.使用createStore方法传入reducer函数生成一个store实例对象
3.使用store实例的subscribe方法 订阅数据的变化(数据一旦变化,可以的到通知)
4.使用store实例的dispatch方法提交action对象触发数据变化(告诉reducer你想怎么改变数据)
5.使用store实例的getState方法获取最新的状态数据跟新到视图中
<button id="decrement">-</button>
<span id="count">0</span>
<button id="increment">+</button>
<script src="https://unpkg.com/redux@latest/dist/redux.min.js"></script>
<script>
// 1. 定义reducer函数
// 作用: 根据不同的action对象,返回不同的新的state
// state: 管理的数据初始状态
// action: 对象 type 标记当前想要做什么样的修改
function reducer (state = { count: 0 }, action) {
// 数据不可变:基于原始状态生成一个新的状态
if (action.type === 'INCREMENT') {
return { count: state.count + 1 }
}
if (action.type === 'DECREMENT') {
return { count: state.count - 1 }
}
return state
}
// 2. 使用reducer函数生成store实例
const store = Redux.createStore(reducer)
// 3. 通过store实例的subscribe订阅数据变化
// 回调函数可以在每次state发生变化的时候自动执行
store.subscribe(() => {
console.log('state变化了', store.getState())
document.getElementById('count').innerText = store.getState().count
})
// 4. 通过store实例的dispatch函数提交action更改状态
const inBtn = document.getElementById('increment')
inBtn.addEventListener('click', () => {
// 增
store.dispatch({
type: 'INCREMENT'
})
})
const dBtn = document.getElementById('decrement')
dBtn.addEventListener('click', () => {
// 减
store.dispatch({
type: 'DECREMENT'
})
})
// 5. 通过store实例的getState方法获取最新状态更新到视图中
</script>
Redux管理数据流程梳理
分为三个核心概念,分别是:state、actin、reducer
1.state -- 一个对象 存放着我们管理的数据状态
2.action -- 一个对象 用来描述想要改的数据
3.reducer -- 一个函数 更具action的描述生成一个新的state
在React项目中使用redux,还需要安装两个插件 - Redux Toolkit 和 react-redux
编写子模块内容
import { createSlice } from "@reduxjs/toolkit";
const counterStore = createSlice({
name:'counter',
//初始状态数据
initialState:{
count:0
},
//修改数据的同步方法
reducers:{
inscrement(state){
state.count++
},
decrement(state){
state.count--
},
}
})
//解构处创建action对象的函数 (actionCreater)
const {inscrement,decrement} = counterStore.actions
//获取reducer函数
const counterReducer = counterStore.reducer
//导出创建action对象的函数和reducer函数
export {inscrement,decrement}
export default counterReducer
编写根store,导入子模块
import { configureStore } from "@reduxjs/toolkit";
import counterReducer from "./modules/counterStore";
//创建根store组合子模块
const store = configureStore({
reducer:{
counter: counterReducer
}
})
export default store
最后为React注入store
内置Provider组件通过store参数把创建好的store实例注入到应用中,链接正式建立。
//导包
import store from './Store';
import { Provider } from 'react-redux';
//注入
<Provider store ={store}>
<App />
</Provider>
React组件使用store中的数据
使用到一个钩子函数 - useSelector ,其作用是把store中的数据映射到组件中
import { useSelector } from "react-redux";
function App() {
const {count} = useSelector(state =>state.counter)
return (
<div className="App">
{count}
</div>
);
}
export default App;
React组件修改store中的数据
React组件修改store中的数据需要借助另外一个hook函数 - useDispatch,它的作用是生成提交action对象的dispatch函数
import {useDispatch, useSelector } from "react-redux";
//导入actionCreater
import { inscrement,decrement } from "./Store/modules/counterStore";
function App() {
const { count } = useSelector(state =>state.counter)
const dispatch = useDispatch()
return (
<div className="App">
<button onClick={()=>dispatch(decrement())}>-</button>
{ count }
<button onClick={()=>dispatch(inscrement())}>+</button>
</div>
);
}
export default App;
提交action传参实现需求
在reducers的同步修改方法中添加action对象参数,在调用actionCreater的时候传递参数,参数会被传递到action对象display属性上
//!!!!!store子模块!!!!!
import { createSlice } from "@reduxjs/toolkit";
const counterStore = createSlice({
name:'counter',
//初始状态数据
initialState:{
count:0
},
//修改数据的同步方法
reducers:{
addToNum(state,action){
state.count = action.payload
}
}
})
//解构处创建action对象的函数 (actionCreater)
const {addToNum} = counterStore.actions
//获取reducer函数
const counterReducer = counterStore.reducer
//导出创建action对象的函数和reducer函数
export {addToNum}
export default counterReducer
//!!!!!React组件内使用!!!!!
import {useDispatch, useSelector } from "react-redux";
//导入actionCreater
import {addToNum} from "./Store/modules/counterStore";
function App() {
const { count } = useSelector(state =>state.counter)
const dispatch = useDispatch()
return (
<div className="App">
{ count }
<button onClick={()=>dispatch(addToNum(10))}>add To 10</button>
<button onClick={()=>dispatch(addToNum(1314))}>add To 1314</button>
<button onClick={()=>dispatch(addToNum(0))}>reset</button>
</div>
);
}
export default App;
Redux与React异步状态操作
样板步骤:
1.创建store的写法不变,配置好同步修改状态的方法
2.单独封装一个函数,在函数内部return一个新函数,在新函数内:
封装异步请求获取数据
调用同步actionCreate传入异步数据生成一个action对象,并使用dispatch提交
3.组件内dispatch的写法保持不变
store子模块
import { createSlice } from "@reduxjs/toolkit";
import axios from "axios";
const channelStore = createSlice({
name:'channel',
initialState:{
channelList:[]
},
reducers:{
setChannels(state,action){
state.channelList = action.payload
}
}
})
//异步请求部分
const {setChannels} = channelStore.actions
const fetchChannlList =()=>{
const url = 'your api url'
return async(dispatch)=>{
const res = await axios.get(url)
dispatch(setChannels(res.data.channels))
}
}
export {fetchChannlList}
const reducer = channelStore.reducer
export default reducer
根store引用
import { configureStore } from "@reduxjs/toolkit";
import channelReducer from "./modules/channelStore"
//创建根store组合子模块
const store = configureStore({
reducer:{
channel: channelReducer
}
})
export default store
React组件内使用
import {useDispatch, useSelector } from "react-redux";
//导入actionCreater
import { useEffect } from "react";
import { fetchChannlList } from "./Store/modules/channelStore";
function App() {
const {channelList} = useSelector(state=>state.channel)
const dispatch = useDispatch()
//使用useEffect触发异步请求执行
useEffect(()=>{
dispatch(fetchChannlList())
},[dispatch])
return (
<div className="App">
<div>
<ul>
{channelList.map(item=><li key={item.id}>{item.name}</li>)}
</ul>
</div>
</div>
);
}
export default App;
Redux调式
使用扩展插件-Redux Devtools