Redux 应用结构

  • /src
    • index.js 应用入口
    • App.js 顶级组件
    • /app
      • store.js 创建 Store 实例
    • components
      • /Counter
        • Counter.js UI 组件
        • counterSlice.js 组件的 Redux 逻辑

创建一个 Redux Store

1
2
3
4
5
6
7
8
9
// /src/app/store.js
import { configureStore } from "@reduxjs/toolkit";
import counterReducer from "../components/Counter/counterSlice";

export default configureStore({
reducer: {
counter: counterReducer,
},
});

在文件counterSlice.js中,会 export 一个 Reducer,我们需要在store.js中导入它。

创建一个 Slice

Slice 是若干 Action 和 Reducer 的集合,它将同一逻辑概念下的碎片化 Action 和 Reducer 整合。

1
2
3
4
5
6
7
8
9
10
11
12
13
// 整合前
import { configureStore } from "@reduxjs/toolkit";
import usersReducer from "../features/users/usersSlice";
import postsReducer from "../features/posts/postsSlice";
import commentsReducer from "../features/comments/commentsSlice";

export default configureStore({
reducer: {
users: usersReducer,
posts: postsReducer,
comments: commentsReducer,
},
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 整合后
// counterSlice.js
import { createSlice } from "@reduxjs/toolkit";

export const counterSlice = createSlice({
name: "counter",
initialState: {
value: 0,
},
reducers: {
increment: (state) => {
state.value += 1;
},
decrement: (state) => {
state.value -= 1;
},
incrementByAmount: (state, action) => {
state.value += action.payload;
},
},
});

export const { increment, decrement, incrementByAmount } = counterSlice.actions;

export default counterSlice.reducer;

Reducer 准则

  • Reducer 应当基于传入的 State 和 Action 所描述的操作执行计算,切忌直接指定 Store 的值。
  • Reducer 不应直接修改现有的 Store,它必须通过复制现有 State 并对复制的值进行更改。
  • Reducer 不应参与任何异步逻辑或其他副作用。

Providing the Store

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// index.js
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import store from "./app/store";
import { Provider } from "react-redux"; // 引入Provider
import * as serviceWorker from "./serviceWorker";

ReactDOM.render(
// 使用Provider包裹App
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
);