Skip to content

ReactJS - 使用 Flux

ReactJS - 使用 Redux Toolkit 进行状态管理

Section titled “ReactJS - 使用 Redux Toolkit 进行状态管理”

虽然 Flux 是一种模式,但 Redux 是一个帮助实现它的流行库。Redux Toolkit 极大地简化了现代 Redux 开发,现在它是推荐的方法。本教程将指导你使用 React 和 Redux Toolkit 设置一个简单的 Todo 应用。

第一步 - 安装 Redux Toolkit 和 React-Redux

Section titled “第一步 - 安装 Redux Toolkit 和 React-Redux”

在你的 React 项目根目录下打开终端或命令提示符,然后运行:

npm install @reduxjs/toolkit react-redux

或者如果你正在使用 Yarn:

yarn add @reduxjs/toolkit react-redux

使用 Redux Toolkit 的常见做法是按‘功能’(features)或‘切片’(slices)组织状态逻辑。对于我们的 Todo 应用,我们将在 src 目录内创建一个 features 目录。

你的 src 文件夹结构可能看起来像这样:

src/
├── app/
│ └── store.js # Redux store configuration
├── features/
│ └── todos/
│ ├── todosSlice.js # Reducer and actions for todos
│ └── Todos.jsx # React component for todos
├── App.js # Main application component
└── index.js # Entry point, renders App

第三步 - 定义 Redux Slice (todosSlice.js)

Section titled “第三步 - 定义 Redux Slice (todosSlice.js)”

一个‘Slice’(切片)是单个功能相关的 Redux Reducer 逻辑和 Action 的集合。Redux Toolkit 的 createSlice 函数会自动生成 Action Creator 和 Action 类型。

import { createSlice } from '@reduxjs/toolkit';
let nextTodoId = 0;
const todosSlice = createSlice({
name: 'todos',
initialState: [],
reducers: {
addTodo: {
reducer(state, action) {
state.push(action.payload); // Immer handles immutability here
},
prepare(text) {
return { payload: { id: nextTodoId++, text, completed: false } };
}
},
toggleTodo(state, action) {
const todo = state.find(todo => todo.id === action.payload);
if (todo) {
todo.completed = !todo.completed;
}
}
}
});
export const { addTodo, toggleTodo } = todosSlice.actions;
export default todosSlice.reducer;

要点:

  • createSlice 接收一个名称、一个初始状态和一个 Reducer 函数对象。
  • 借助 Redux Toolkit 内部运行的 Immer,Reducer 函数可以直接‘修改’(mutate)状态。
  • addTodo 中的 prepare 回调允许自定义 Action 的有效载荷(payload),这里我们生成一个唯一的 ID。
  • Action Creator(addTodo、toggleTodo)会自动生成并导出。

Redux Toolkit 的 configureStore 简化了 Store 的设置。

import { configureStore } from '@reduxjs/toolkit';
import todosReducer from '../features/todos/todosSlice';
export const store = configureStore({
reducer: {
todos: todosReducer,
// other reducers can be added here
},
});

第五步 - 将 Store 提供给 React (index.js)

Section titled “第五步 - 将 Store 提供给 React (index.js)”

使用来自 react-redux 的 <Provider> 组件包裹你的根应用组件,以便让 Store 对所有组件可用。

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'; // Assuming you have some basic styling
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);

第六步 - 在组件中使用 Redux 状态和 Action (Todos.jsx 和 App.js)

Section titled “第六步 - 在组件中使用 Redux 状态和 Action (Todos.jsx 和 App.js)”

我们将使用 useSelector Hook 从 Store 中读取数据,并使用 useDispatch 来调度(dispatch)Action。

import React, { useState, useRef } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { addTodo, toggleTodo } from './todosSlice';
function Todos() {
const todos = useSelector(state => state.todos);
const dispatch = useDispatch();
const [text, setText] = useState('');
const inputRef = useRef(null);
const handleAddTodo = (e) => {
e.preventDefault();
if (text.trim()) {
dispatch(addTodo(text.trim()));
setText('');
inputRef.current.focus();
}
};
return (
<div>
<form onSubmit={handleAddTodo}>
<input
type="text"
value={text}
onChange={(e) => setText(e.target.value)}
ref={inputRef}
placeholder="What needs to be done?"
/>
<button type="submit">Add Todo</button>
</form>
<ul>
{todos.map(todo => (
<li
key={todo.id}
onClick={() => dispatch(toggleTodo(todo.id))}
style={{ textDecoration: todo.completed ? 'line-through' : 'none', cursor: 'pointer' }}
>
{todo.text}
</li>
))}
</ul>
</div>
);
}
export default Todos;

现在,我们将 Todos 组件集成到 App.js 中。

import React from 'react';
import Todos from './features/todos/Todos';
import './App.css'; // Assuming you have some basic styling
function App() {
return (
<div className="App">
<header className="App-header">
<h1>Todo List with Redux Toolkit</h1>
</header>
<main>
<Todos />
</main>
</div>
);
}
export default App;

通过这些步骤,你就拥有了一个使用 React 和 Redux Toolkit 构建的正常工作的 Todo 应用。你可以添加新的待办事项并切换它们的完成状态。这展示了使用 Redux 的现代、简化的方式。

常见陷阱与进一步学习:

  • 忘记将 App 包裹在 <Provider> 中。
  • 使用 useSelector 选择状态时出错(确保你的 state.featureName 与 Store 配置匹配)。
  • 对于更复杂的应用,可以探索使用 createAsyncThunk 和 Redux Thunk 等中间件(Redux Toolkit 默认包含)处理异步逻辑。
  • 参考 Redux Toolkit 官方文档了解高级模式:https://redux-toolkit.js.org/