Appearance
Redux 状态管理器
Redux 核心主要有 Store、Action、Reducer。
数据流向:在 Redux 中,数据是单向流动的。简单来说就是:
- 用户在界面上进行操作(如点击按钮)。
- 触发一个 Action 的派发(dispatch)。
- Store 调用对应的 Reducer,传入旧的 state 和这个 Action。
- Reducer 根据 Action 的类型返回一个新的 state。
- Store 的 state 更新,React 组件监听到变化并重新渲染。
首先需要安装 react-redux 和 @reduxjs/toolkit 这两个包
bash
npm install react-redux @reduxjs/toolkitnpm install react-redux @reduxjs/toolkit创建 Redux Store
创建一个 src/store/store.js 文件
js
import { configureStore } from "@reduxjs/toolkit";
export const store = configureStore({
reducer: {
// 这里将是我们之后创建的各个模块的 reducer
},
});import { configureStore } from "@reduxjs/toolkit";
export const store = configureStore({
reducer: {
// 这里将是我们之后创建的各个模块的 reducer
},
});将 Store 提供给 React 应用
整个 React 应用都可以访问到 Redux Store 了。
js
// src/index.js
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { store } from "./store/store";
import { Provider } from "react-redux";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);// src/index.js
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { store } from "./store/store";
import { Provider } from "react-redux";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);创建 Slice(状态切片)
在 Vuex 中,有 state, mutations, actions, getters 这些概念。在 Redux Toolkit 中,一个类似的概念叫做 Slice。Slice 将与某个功能相关的 state、reducers(类似 mutations)和 actions 集中在一个文件里进行管理。
js
// src/features/counter/counterSlice.js
import { createSlice } from "@reduxjs/toolkit";
const initialState = {
value: 0,
};
export const counterSlice = createSlice({
name: "counter", // slice 的名称
initialState, // 初始状态
// 定义 reducers,这里的函数会自动生成对应的 actions
reducers: {
increment: (state) => {
// Redux Toolkit 内部使用了 Immer,所以可以直接“修改” state
state.value += 1;
},
decrement: (state) => {
state.value -= 1;
},
// 接收 payload 的 action
incrementByAmount: (state, action) => {
state.value += action.payload;
},
},
});
// 导出 reducers 中定义的 action creator 函数
export const { increment, decrement, incrementByAmount } = counterSlice.actions;
// 默认导出 reducer
export default counterSlice.reducer;// src/features/counter/counterSlice.js
import { createSlice } from "@reduxjs/toolkit";
const initialState = {
value: 0,
};
export const counterSlice = createSlice({
name: "counter", // slice 的名称
initialState, // 初始状态
// 定义 reducers,这里的函数会自动生成对应的 actions
reducers: {
increment: (state) => {
// Redux Toolkit 内部使用了 Immer,所以可以直接“修改” state
state.value += 1;
},
decrement: (state) => {
state.value -= 1;
},
// 接收 payload 的 action
incrementByAmount: (state, action) => {
state.value += action.payload;
},
},
});
// 导出 reducers 中定义的 action creator 函数
export const { increment, decrement, incrementByAmount } = counterSlice.actions;
// 默认导出 reducer
export default counterSlice.reducer;将 Slice 的 Reducer 添加到 Store 中
js
// src/app/store.js
import { configureStore } from "@reduxjs/toolkit";
import counterReducer from "../features/counter/counterSlice"; // 导入 counter 的 reducer
export const store = configureStore({
reducer: {
counter: counterReducer, // 将 counter reducer 添加到 store 中
},
});// src/app/store.js
import { configureStore } from "@reduxjs/toolkit";
import counterReducer from "../features/counter/counterSlice"; // 导入 counter 的 reducer
export const store = configureStore({
reducer: {
counter: counterReducer, // 将 counter reducer 添加到 store 中
},
});在 React 组件中使用 Redux State 和 Actions
react-redux 提供了两个关键的 Hooks 来实现这一点:useSelector 和 useDispatch。
js
// src/features/counter/Counter.js
import React from "react";
import { useSelector, useDispatch } from "react-redux";
import { decrement, increment, incrementByAmount } from "./counterSlice";
export function Counter() {
// useSelector 用于从 store 中读取 state
const count = useSelector((state) => state.counter.value);
// useDispatch 用于获取 dispatch 函数,派发 action
const dispatch = useDispatch();
return (
<div>
<div>
<button
aria-label="Increment value"
onClick={() => dispatch(increment())}
>
增加
</button>
<span>{count}</span>
<button
aria-label="Decrement value"
onClick={() => dispatch(decrement())}
>
减少
</button>
<button onClick={() => dispatch(incrementByAmount(5))}>增加 5</button>
</div>
</div>
);
}// src/features/counter/Counter.js
import React from "react";
import { useSelector, useDispatch } from "react-redux";
import { decrement, increment, incrementByAmount } from "./counterSlice";
export function Counter() {
// useSelector 用于从 store 中读取 state
const count = useSelector((state) => state.counter.value);
// useDispatch 用于获取 dispatch 函数,派发 action
const dispatch = useDispatch();
return (
<div>
<div>
<button
aria-label="Increment value"
onClick={() => dispatch(increment())}
>
增加
</button>
<span>{count}</span>
<button
aria-label="Decrement value"
onClick={() => dispatch(decrement())}
>
减少
</button>
<button onClick={() => dispatch(incrementByAmount(5))}>增加 5</button>
</div>
</div>
);
}
小洛的前端技术博客