React Redux 状态管理:从基础到实战(TodoList 案例)
React Redux 状态管理:从基础到实战(TodoList 案例)
一、Redux 核心概念
-
Store
全局状态容器,存储应用所有状态
$$ \text{Store} = {\text{state}, \text{reducers}, \text{middleware}} $$ -
Action
描述状态变更的普通对象,必须包含type属性{ type: 'ADD_TODO', payload: 'Learn Redux' } -
Reducer
纯函数,接收当前状态和 action,返回新状态
$$ \text{newState} = \text{reducer}(\text{currentState}, \text{action}) $$ -
Dispatch
触发状态更新的唯一方式:store.dispatch(action)
二、React-Redux 集成
-
Provider 组件
包裹根组件,传递 store 到所有子组件import { Provider } from 'react-redux'; import store from './store'; ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') ); -
connect 高阶组件
连接 React 组件与 Redux storeimport { connect } from 'react-redux'; const TodoList = ({ todos }) => ( /* JSX */ ); const mapStateToProps = state => ({ todos: state.todos }); export default connect(mapStateToProps)(TodoList);
三、TodoList 实战实现
1. 状态结构设计
{
todos: [
{ id: 1, text: "Buy milk", completed: false },
{ id: 2, text: "Learn Redux", completed: true }
],
filter: "SHOW_ALL" // SHOW_COMPLETED/SHOW_ACTIVE
}
2. Action 创建函数
// actions.js
let nextId = 0;
export const addTodo = text => ({
type: 'ADD_TODO',
payload: { id: nextId++, text, completed: false }
});
export const toggleTodo = id => ({
type: 'TOGGLE_TODO',
payload: id
});
3. Reducer 实现
// reducer.js
const initialState = { todos: [], filter: 'SHOW_ALL' };
export default (state = initialState, action) => {
switch (action.type) {
case 'ADD_TODO':
return { ...state, todos: [...state.todos, action.payload] };
case 'TOGGLE_TODO':
return {
...state,
todos: state.todos.map(todo =>
todo.id === action.payload
? { ...todo, completed: !todo.completed }
: todo
)
};
default:
return state;
}
};
4. 容器组件
// TodoListContainer.js
import { connect } from 'react-redux';
import { addTodo, toggleTodo } from './actions';
const TodoList = ({ todos, dispatch }) => (
<div>
<input
type="text"
onKeyPress={e => e.key === 'Enter' && dispatch(addTodo(e.target.value))}
/>
<ul>
{todos.map(todo => (
<li
key={todo.id}
onClick={() => dispatch(toggleTodo(todo.id))}
style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}
>
{todo.text}
</li>
))}
</ul>
</div>
);
const mapStateToProps = state => ({ todos: state.todos });
export default connect(mapStateToProps)(TodoList);
5. 过滤功能扩展
// 添加过滤器action
export const setFilter = filter => ({ type: 'SET_FILTER', payload: filter });
// 更新reducer
case 'SET_FILTER':
return { ...state, filter: action.payload };
// 在组件中使用
const getVisibleTodos = (todos, filter) => {
switch (filter) {
case 'SHOW_COMPLETED': return todos.filter(t => t.completed);
case 'SHOW_ACTIVE': return todos.filter(t => !t.completed);
default: return todos;
}
};
四、最佳实践
-
使用 Redux Toolkit
简化 action/reducer 创建:import { createSlice } from '@reduxjs/toolkit'; const todoSlice = createSlice({ name: 'todos', initialState: [], reducers: { addTodo: (state, action) => [...state, action.payload], toggleTodo: (state, action) => state.map(todo => todo.id === action.payload ? {...todo, completed: !todo.completed} : todo ) } }); -
异步处理
使用 Redux Thunk 处理 API 请求:export const fetchTodos = () => async dispatch => { const response = await axios.get('/api/todos'); dispatch({ type: 'LOAD_TODOS', payload: response.data }); }; -
性能优化
使用React.memo避免不必要的重渲染:const TodoItem = React.memo(({ todo, onToggle }) => ( <li onClick={() => onToggle(todo.id)}>{todo.text}</li> ));
五、完整项目结构
src/
├── store/
│ ├── index.js # Store 初始化
│ ├── actions.js # Action 创建器
│ ├── reducers.js # Root reducer
│ └── slices/ # Redux Toolkit 切片
├── components/ # 展示组件
└── containers/ # 容器组件
通过 TodoList 案例,可深入理解 Redux 单向数据流: $$ \text{Action} \rightarrow \text{Reducer} \rightarrow \text{Store} \rightarrow \text{View} \xrightarrow{\text{User Input}} \text{Action} $$ 该模式确保状态变更可预测且易于调试,适用于中大型应用开发。
更多推荐
所有评论(0)