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 扩展程序。
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 组件。
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 函数。
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 creatorexport 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 应用,作为练习,以进一步巩固你的理解。
更多详情,请参考官方文档:
- Redux Toolkit: https://redux-toolkit.js.org/
- React Redux: https://react-redux.js.org/