目录
- 1 概念
- 2 Redux 安装
- 3 创建子模块并导入
- 4 中间件为 react 注入 store
- 5 在组件中使用 store 数据
- 6 修改 store 数据
- 7 提交 action 传参
- 8 异步状态操作
- 9 redux 调试工具
1 概念
Redux 是一个全局状态管理的 JS 库
2 Redux 安装
在react中使用redux,官方要求安装两个其他插件:Redux Toolkit 和 react-redux
- Redux Toolkit:官方推荐编写redux逻辑的方式,简化书写方式
- react-redux:用来连接 redux 和 react 组件的中间件
通过命令:
npm i @reduxjs/toolkit react-redux
3 创建子模块并导入
创建如下目录结构
counterStore.js 代码如下:
import { createSlice } from "@reduxjs/toolkit";
const counterStore = createSlice({
name: 'counter',
// 初始化state
initialState: {
count: 0
},
// 修改状态的方法 (同步方法)
reducers: {
increment(state) {
state.count++
},
decrement(state) {
state.count--
}
}
})
// 解构出来action函数
const { increment, decrement } = counterStore.actions
// 获取reducer
const reducer = counterStore.reducer
// 导出actions
export { increment, decrement }
// 默认导出reducer
export default reducer
其中,我们定义了数据:count
以及两个 action:increment / decrement,后续会通过 dispatch 来触发 action 修改数据
react 只有一种方式能够修改数据,就是 action,我们需要用 dispatch 提交 action,来修改数据
然后再将子模块 counterStore.js 引入
index.js 代码如下:
import { configureStore } from '@reduxjs/toolkit'
import counter from './modules/counterStore'
// 导入子模块reducer
export default configureStore({
reducer: {
counter
}
})
4 中间件为 react 注入 store
react-redux 负责把 react 和 redux 连接起来,内置 Provider 组件 通过 store 参数把创建好的 store 实例注入到应用中,连接正式建立
通过导入 store 和 Provider 后
使用 Provider 将 App 包裹起来
import store from "./store";
import { Provider } from "react-redux";
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);
5 在组件中使用 store 数据
需要用到一个钩子函数 useSelector(),他的作用是把 store 的数据映射到组件中
import './App.css';
import { useSelector } from "react-redux";
function App() {
// 获得 count 数据
const { count } = useSelector(state => state.counter)
return (
<div className="App">
{count}
</div>
);
}
export default App;
使用 {count} 语法,界面中会展示 count 初始值
6 修改 store 数据
需要另外一个 hook 函数 userDispatch,它的作用是生成提交 action 对象的 dispatch 函数
react 只有一种方式能够修改数据,就是 action,我们需要用 dispatch 提交 action,来修改数据
import './App.css';
import { useDispatch, useSelector } from "react-redux";
// 导入action
import { increment, decrement } from './store/modules/counterStore.js'
function App() {
// 获得 count 数据
const { count } = useSelector(state => state.counter)
// 通过 dispatch 提交action 修改数据
const dispatch = useDispatch()
return (
<div className="App">
<button onClick={() => dispatch(decrement())}>-</button>
{count}
<button onClick={() => dispatch(increment())}>+</button>
</div>
);
}
export default App;
7 提交 action 传参
在调用 action 时,参数会被传递到 action 对象的 payload 属性上
import './App.css';
import { useDispatch, useSelector } from "react-redux";
// 导入action
import { increment, decrement, addToNum } from './store/modules/counterStore.js'
function App() {
// 获得 count 数据
const { count } = useSelector(state => state.counter)
// dispatch 提交action 修改数据
const dispatch = useDispatch()
return (
<div className="App">
<button onClick={() => dispatch(decrement())}>-</button>
{count}
<button onClick={() => dispatch(increment())}>+</button>
<button onClick={() => dispatch(addToNum(10))}>+10</button>
</div>
);
}
export default App;
import { createSlice } from "@reduxjs/toolkit";
const counterStore = createSlice({
name: 'counter',
// 初始化state
initialState: {
count: 0
},
// 修改状态的方法 (同步方法)
reducers: {
increment(state) {
state.count++
},
decrement(state) {
state.count--
},
addToNum(state, action) {
state.count += action.payload
}
}
})
// 解构出来action函数
const { increment, decrement, addToNum } = counterStore.actions
// 获取reducer
const reducer = counterStore.reducer
// 导出actions
export { increment, decrement, addToNum }
// 默认导出reducer
export default reducer
8 异步状态操作
- 创建 store 的 state 和 action 不变
- 在子模块中单独封装一个函数,新函数中异步请求拿到数据,并使用 dispatch 触发 action
创建新的 store 模块
store/modules/channelStore.js 代码如下:
import { createSlice } from "@reduxjs/toolkit";
const channelStore = createSlice({
name: 'channel',
// 初始化state
initialState: {
channel: [{id: 50}, {id: 100}]
},
// 修改状态的方法 (同步方法)
reducers: {
setChannels(state, action) {
state.channel = action.payload
}
}
})
// 解构出来action函数
const { setChannels } = channelStore.actions
// 获取reducer
const reducer = channelStore.reducer
// 异步请求
const fetchChannList = () => {
return async (dispatch) => {
setTimeout(() => {
dispatch(setChannels([{id: 50}, {id: 100}, {id: 150}, {id: 200}]))
}) // 模拟产生异步请求
console.log('aaa')
}
}
// 导出异步方法
export { fetchChannList }
// 默认导出reducer
export default reducer
App.js 代码如下:
import './App.css';
import { useEffect } from 'react';
import { useDispatch, useSelector } from "react-redux";
// 导入action
import { increment, decrement, addToNum } from './store/modules/counterStore.js'
import { fetchChannList } from './store/modules/channelStore.js'
function App() {
// 获得 state 数据
const { count } = useSelector(state => state.counter)
const { channel } = useSelector(state => state.channel)
// dispatch 提交action 修改数据
const dispatch = useDispatch()
// 使用useEffect触发异步请求
useEffect(() => {
dispatch(fetchChannList())
}, [dispatch])
return (
<div className="App">
<button onClick={() => dispatch(decrement())}>-</button>
{count}
<button onClick={() => dispatch(increment())}>+</button>
<button onClick={() => dispatch(addToNum(10))}>+10</button>
<ul>
{channel.map(item => <li key={item.id}>{item.id}</li>)}
</ul>
</div>
);
}
export default App;
9 redux 调试工具
谷歌下载:redux devtools