Redux
Redux
是React
中常用的状态管理组件,类似于Vue
中的Pinia(Vuex)
,可以独立于框架运行
作用: 通过集中管理的方式管理应用的状态
配套工具
在react
中使用redux
,官方要求按照两个插件,Redux Toolkit
和 react-redux
Redux Toolkit
是官方推荐编写Redux
逻辑的方式,是一套工具的集合集,简化书写方式
react-redux
用来连接redux
和 react
组件的中间件
npm i @reduxjs/toolkit react-redux
store目录结构设计
- 通常集中状态管理的部分都会单独创建一个
store
目录 - 应用通常会有多个子
store
模块,所以创建一个modules
目录,在内部编写业务分类的子store
store
中的入口文件index.js
的作用是组合modules
中所有的子模块,并导出store
使用
counterStore.js
import { createSlice } from "@reduxjs/toolkit";
const counterStore = createSlice({
// 名称
name: "counter",
// 初始化状态
initialState:{
count:0
},
//修改数据的同步方法
reducers:{
add(store){
store.count++
},
sub(store){
store.count--
}
}
})
// 结构出action对象中的函数
const {add,sub} = counterStore.actions
// reducer函数
const currentReducer = counterStore.reducer
// 导出
export default currentReducer
export {add,sub}
index.js
import { configureStore } from "@reduxjs/toolkit";
import counterReducer from "./modules/counterStore";
// 创建根store组合子模块
const store = configureStore({
reducer:{
counter:counterReducer
}
})
export default store;
为react注入store
react-redux
负责把Redux
和React
连接起来,内置Provider
组件,通过store
参数把创建好的store
实例注入到应用中。
main.jsx
项目的入口文件
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.jsx'
import './index.css'
import store from './store'
import { Provider } from 'react-redux'
createRoot(document.getElementById('root')).render(
<StrictMode>
<Provider store={store}>
<App />
</Provider>
</StrictMode>,
)
在组件中使用
在react
组件中使用store
中的数据,需要用到一个钩子函数useSelector
,它的作用是把store
中的数据映射到组件中
function App() {
const counterReducer = useSelector(state => state.counter);
return (
<div>
<div>当前值:{counterReducer.count}</div>
</div>
);
}
React
组件中修改store
中的数据需要借助另外一个hook
函数——useDispatch
,它的作用是生成提交action
对象的dispatch
函数
import './App.css'
import { useSelector,useDispatch } from 'react-redux';
// 导入创建的action对象的方法
import { add, sub } from './store/modules/counterStore';
function App() {
const counterReducer = useSelector(state => state.counter);
// 获取dispatch函数
const dispatch = useDispatch();
return (
<div>
<div>当前值:{counterReducer.count}</div>
{/* 调用 */}
<button onClick={() => dispatch(add())}>加一</button>
<button onClick={() => dispatch(sub())}>减一</button>
</div>
);
}
提交action
传参
在reducers
的同步修改方法中添加action
对象参数,在调用ationCreater
的时候传递参数,参数会被传递到action
对象的payload
属性上
import { createSlice } from "@reduxjs/toolkit";
const counterStore = createSlice({
// 名称
name: "counter",
// 初始化状态
initialState:{
count:0
},
//修改数据的同步方法
reducers:{
add(store){
store.count++
},
sub(store){
store.count--
},
addNum(store,action){
store.count+= action.payload
}
}
})
// 结构出action对象中的函数
const {add,sub,addNum} = counterStore.actions
// reducer函数
const currentReducer = counterStore.reducer
// 导出
export default currentReducer
export {add,sub,addNum}
在这里插入代码片
import './App.css'
import { useSelector,useDispatch } from 'react-redux';
// 导入创建的action对象的方法
import { add, sub,addNum } from './store/modules/counterStore';
function App() {
const counterReducer = useSelector(state => state.counter);
// 获取dispatch函数
const dispatch = useDispatch();
return (
<div>
<div>当前值:{counterReducer.count}</div>
{/* 调用 */}
<button onClick={() => dispatch(add())}>加一</button>
<button onClick={() => dispatch(sub())}>减一</button>
{/* 加三 */}
<button onClick={() => dispatch(addNum(3))}>加三</button>
</div>
);
}
异步操作
- 创建
store
的方式不变,配置好同步修改状态的方法 - 单独封装一个函数,在函数内部
return
一个新函数,在新函数中- 封装异步请求获取数据
- 调用同步
actionCreate
传入异步数据生成的一个action
对象,并使用dispatch
提交
- 组件中
dispatch
的写法不变
englishStore.js
import { createSlice } from "@reduxjs/toolkit";
const englishStore = createSlice({
name: "englishstore",
// 初始化状态
initialState: {
// 英文内容
content: "",
// 中文内容
note: "",
},
// 修改内容
reducers: {
changeEnglish(store, action) {
console.log(action.payload);
store.content = action.payload.content;
store.note = action.payload.note;
},
},
});
// 结构出action对象中的方法
const { changeEnglish } = englishStore.actions;
// 异步请求
const fetchEnglish = () => {
return async (dispatch) => {
const res = await fetch("https://api.oioweb.cn/api/common/OneDayEnglish");
const data = await res.json();
console.log(data);
// 修改状态
dispatch(changeEnglish(data.result));
};
};
// reducer函数
const englishReducer = englishStore.reducer;
// 导出
export default englishReducer;
export { fetchEnglish };
使用
import { useEffect } from 'react';
import './App.css'
import { useSelector, useDispatch } from 'react-redux';
import { fetchEnglish } from './store/modules/englishStore';
function App() {
const englishReducer = useSelector(state => state.english)
const dispatch = useDispatch()
useEffect(() => {
// 触发异步请求
dispatch(fetchEnglish())
}, [dispatch])
return (
<div>
<div>中文:{englishReducer.note}</div>
<div>英文:{englishReducer.content}</div>
</div>
);
}
export default App