Skip to content

Redux - React 示例

Redux - 使用 Redux Toolkit 的 React 示例

Section titled “Redux - 使用 Redux Toolkit 的 React 示例”

让我们来看一个将 React 与 Redux 集成的简单示例,使用现代最佳实践,特别是 Redux Toolkit 和 React Redux Hooks。我们将构建一个基本的计数器应用。

首先,我们使用 Redux Toolkit 中的 configureStore 函数来设置 Redux store。这个函数简化了 store 的配置,自动包含了 Redux Thunk 中间件,并启用了 Redux DevTools 扩展程序。

src/app/store.js
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from '../features/counter/counterSlice';
export const store = configureStore({
reducer: {
counter: counterReducer,
},
});
// 可选:为 TypeScript 集成定义 RootState 和 AppDispatch 类型
// export type RootState = ReturnType<typeof store.getState>;
// export type AppDispatch = typeof store.dispatch;

接下来,根文件 (index.js 或 main.jsx) 渲染 React 应用程序,并使用 react-redux 中的 <Provider> 组件进行包装。Provider 组件使得 Redux store 在应用程序中的所有组件中都可用。

// src/index.js (或 main.jsx)
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import { store } from './app/store';
import App from './App';
import './index.css';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);

我们的根 App 组件只是简单地渲染 Counter 组件。

src/App.js
import React from 'react';
import Counter from './features/counter/Counter';
import './App.css';
function App() {
return (
<div className="App">
<header className="App-header">
<Counter />
</header>
</div>
);
}
export default App;

Counter 组件使用 React Redux 的 hook 来与 store 交互。useSelector 从 store 中读取数据,而 useDispatch 获取用于分发 actions 的 dispatch 函数。

src/features/counter/Counter.js
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement, reset } from './counterSlice'; // 从 slice 导入 actions
function Counter() {
// 从 Redux store state 中读取计数器值
const count = useSelector((state) => state.counter.value);
// 获取 dispatch 函数
const dispatch = useDispatch();
return (
<div>
<div>
<h2>计数器值: {count}</h2>
</div>
<div>
<button onClick={() => dispatch(increment())}>
增加 1
</button>
</div>
<div>
<button onClick={() => dispatch(decrement())}>
减少 1
</button>
</div>
<button onClick={() => dispatch(reset())}>
重置
</button>
</div>
);
}
export default Counter;

Redux Toolkit 的 createSlice 函数简化了 reducer 和 action 的创建。它会自动生成 action creator 和 action type,并在内部使用 Immer,允许你在 reducer 中编写看起来像“可变”的逻辑,但 Immer 会将其转换为安全的不可变更新。

// src/features/counter/counterSlice.js
import { createSlice } from '@reduxjs/toolkit';
const initialState = {
value: 0,
};
export const counterSlice = createSlice({
name: 'counter', // 在 action types 中使用的名称
initialState,
// `reducers` 字段允许我们定义 reducer 并生成相关的 action
reducers: {
increment: (state) => {
// Redux Toolkit 允许我们在 reducer 中编写“可变”逻辑。
// 它实际上并没有改变 state,因为它使用了 Immer 库,
// Immer 会检测“草稿 state”的变化,并生成一个全新的
// 不可变 state
state.value += 1;
},
decrement: (state) => {
state.value -= 1;
},
reset: (state) => {
state.value = 0;
},
// 带有 payload 的示例:incrementByAmount: (state, action) => {
// state.value += action.payload;
// },
},
});
// 每个 case reducer 函数都会生成对应的 Action creator
export const { increment, decrement, reset } = counterSlice.actions;
// 下面的函数称为 selector,它允许我们从
// state 中选择一个值。Selector 也可以在使用的地方内联定义,而不是
// 在 slice 文件中。例如:`useSelector((state) => state.counter.value)`
// export const selectCount = (state) => state.counter.value;
// 导出由 createSlice 生成的 reducer 函数
export default counterSlice.reducer;

最初,应用显示的计数器值为 0。

当你点击两次 ‘INCREMENT BY 1’,显示的值会变为 2。

点击一次 ‘DECREMENT BY 1’ 会将值改为 1。

点击 ‘RESET’ 会将计数器值重置为 0。

使用 Redux DevTools 浏览器扩展程序,你可以检查被分发的 actions 以及产生的 state 变化。例如,在第一次递增后,你会看到一个类型为 ‘counter/increment’ 的 action,并且 state 从 { value: 0 } 变为 { value: 1 }。DevTools 支持时光旅行调试、检查 action 的 payload 以及查看 state 的差异。

我们建议你尝试使用 Redux Toolkit 和 React Hooks 构建一个小的 Todo 应用,作为练习,以进一步巩固你的理解。

更多详情,请参考官方文档: