Redux、Context API、状态管理最佳实践
本课程将详细介绍React应用中的状态管理相关知识和实践技巧,包括React内置的状态管理方案、Redux的基本使用、Redux Toolkit的最佳实践等核心概念。
// useState基本使用
import React, { useState } from 'react';
function Counter() {
// 声明一个名为count的状态变量,初始值为0
const [count, setCount] = useState(0);
// 声明多个状态变量
const [name, setName] = useState('React');
const [isVisible, setIsVisible] = useState(true);
return (
计数器: {count}
名称: {name}
setName(e.target.value)}
/>
可见性: {isVisible ? '可见' : '隐藏'}
);
}
export default Counter;
// useReducer基本使用
import React, { useReducer } from 'react';
// 定义初始状态
const initialState = {
count: 0,
step: 1
};
// 定义reducer函数
function counterReducer(state, action) {
switch (action.type) {
case 'increment':
return { ...state, count: state.count + state.step };
case 'decrement':
return { ...state, count: state.count - state.step };
case 'reset':
return { ...state, count: 0 };
case 'setStep':
return { ...state, step: action.payload };
default:
return state;
}
}
function CounterWithReducer() {
// 使用useReducer
const [state, dispatch] = useReducer(counterReducer, initialState);
return (
计数器: {state.count}
步长: {state.step}
dispatch({
type: 'setStep',
payload: parseInt(e.target.value) || 1
})}
/>
);
}
export default CounterWithReducer;
// Context API基本使用
import React, { createContext, useContext, useState } from 'react';
// 创建Context
const ThemeContext = createContext();
// 创建Provider组件
export function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
const toggleTheme = () => {
setTheme(prevTheme => prevTheme === 'light' ? 'dark' : 'light');
};
const value = {
theme,
toggleTheme
};
return (
{children}
);
}
// 创建自定义Hook
export function useTheme() {
const context = useContext(ThemeContext);
if (!context) {
throw new Error('useTheme must be used within a ThemeProvider');
}
return context;
}
// 使用Context的组件
function ThemedButton() {
const { theme, toggleTheme } = useTheme();
return (
);
}
// 应用根组件
function App() {
return (
Context API示例
);
}
export default App;
// Redux基本配置
// 1. 安装Redux和React-Redux
// npm install redux react-redux
// 2. 创建action types
const INCREMENT = 'counter/increment';
const DECREMENT = 'counter/decrement';
const RESET = 'counter/reset';
const SET_STEP = 'counter/setStep';
// 3. 创建action creators
export const increment = () => ({
type: INCREMENT
});
export const decrement = () => ({
type: DECREMENT
});
export const reset = () => ({
type: RESET
});
export const setStep = (step) => ({
type: SET_STEP,
payload: step
});
// 4. 创建reducer
const initialState = {
count: 0,
step: 1
};
export function counterReducer(state = initialState, action) {
switch (action.type) {
case INCREMENT:
return {
...state,
count: state.count + state.step
};
case DECREMENT:
return {
...state,
count: state.count - state.step
};
case RESET:
return {
...state,
count: 0
};
case SET_STEP:
return {
...state,
step: action.payload
};
default:
return state;
}
}
// 5. 创建store
import { createStore } from 'redux';
import { counterReducer } from './reducers';
export const store = createStore(counterReducer);
// 6. 在React应用中使用Redux
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import { store } from './store';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
);
// 7. 在组件中使用Redux
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement, reset, setStep } from './actions';
function Counter() {
// 从store中获取状态
const { count, step } = useSelector(state => state);
// 获取dispatch方法
const dispatch = useDispatch();
return (
Redux计数器: {count}
步长: {step}
dispatch(setStep(parseInt(e.target.value) || 1))}
/>
);
}
export default Counter;
Redux Toolkit是官方推荐的Redux开发工具集,它简化了Redux的使用,减少了样板代码。
// Redux Toolkit基本使用
// 1. 安装Redux Toolkit和React-Redux
// npm install @reduxjs/toolkit react-redux
// 2. 创建slice
import { createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counter',
initialState: {
count: 0,
step: 1
},
reducers: {
increment: (state) => {
// Redux Toolkit允许我们在reducers中直接修改状态
state.count += state.step;
},
decrement: (state) => {
state.count -= state.step;
},
reset: (state) => {
state.count = 0;
},
setStep: (state, action) => {
state.step = action.payload;
}
}
});
// 导出action creators
export const { increment, decrement, reset, setStep } = counterSlice.actions;
// 导出reducer
export default counterSlice.reducer;
// 3. 配置store
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './features/counter/counterSlice';
import todoReducer from './features/todo/todoSlice';
export const store = configureStore({
reducer: {
counter: counterReducer,
todo: todoReducer
}
});
// 4. 在组件中使用
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement, reset, setStep } from './features/counter/counterSlice';
function Counter() {
const { count, step } = useSelector(state => state.counter);
const dispatch = useDispatch();
return (
Redux Toolkit计数器: {count}
步长: {step}
dispatch(setStep(parseInt(e.target.value) || 1))}
/>
);
}
export default Counter;
// 异步状态管理
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import { fetchTodos } from '../services/api';
// 创建异步thunk
export const getTodos = createAsyncThunk(
'todo/fetchTodos',
async (_, { rejectWithValue }) => {
try {
const response = await fetchTodos();
return response;
} catch (error) {
return rejectWithValue(error.message);
}
}
);
// 创建todo slice
const todoSlice = createSlice({
name: 'todo',
initialState: {
items: [],
status: 'idle', // idle, loading, succeeded, failed
error: null
},
reducers: {
addTodo: (state, action) => {
state.items.push(action.payload);
},
removeTodo: (state, action) => {
state.items = state.items.filter(todo => todo.id !== action.payload);
},
updateTodo: (state, action) => {
const index = state.items.findIndex(todo => todo.id === action.payload.id);
if (index !== -1) {
state.items[index] = action.payload;
}
}
},
extraReducers: (builder) => {
builder
.addCase(getTodos.pending, (state) => {
state.status = 'loading';
})
.addCase(getTodos.fulfilled, (state, action) => {
state.status = 'succeeded';
state.items = action.payload;
})
.addCase(getTodos.rejected, (state, action) => {
state.status = 'failed';
state.error = action.payload;
});
}
});
export const { addTodo, removeTodo, updateTodo } = todoSlice.actions;
export default todoSlice.reducer;
// 在组件中使用
import React, { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { getTodos, addTodo, removeTodo } from './features/todo/todoSlice';
function TodoList() {
const { items, status, error } = useSelector(state => state.todo);
const dispatch = useDispatch();
useEffect(() => {
if (status === 'idle') {
dispatch(getTodos());
}
}, [status, dispatch]);
const handleAddTodo = () => {
const newTodo = {
id: Date.now(),
text: `Todo ${items.length + 1}`,
completed: false
};
dispatch(addTodo(newTodo));
};
return (
Todo列表
{status === 'loading' && 加载中...}
{status === 'failed' && 错误: {error}}
{items.map(todo => (
-
{todo.text}
))}
);
}
export default TodoList;
| 状态管理方案 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| useState | 组件内部简单状态 | 简单易用,内置Hook | 不适合复杂状态和跨组件共享 |
| useReducer | 组件内部复杂状态 | 适合复杂状态逻辑,可预测性强 | 需要编写更多代码 |
| Context API | 跨组件简单状态共享 | 内置API,无需额外依赖 | 可能导致不必要的重渲染 |
| Redux | 大型应用全局状态管理 | 可预测性强,工具生态丰富 | 样板代码多,学习曲线陡 |
| Redux Toolkit | 大型应用全局状态管理 | 简化Redux使用,减少样板代码 | 仍有一定学习曲线 |
使用useState和useReducer实现一个计数器应用,包含以下功能:
使用Context API实现一个主题切换功能,包含以下功能:
使用Redux Toolkit实现一个待办事项应用,包含以下功能:
构建一个完整的React应用,使用适当的状态管理方案:
通过本课程学习,你应该掌握了React状态管理的核心知识和实践技巧:
状态管理是React应用开发中的重要组成部分,合理的状态管理方案可以提高应用的可维护性和性能。继续深入学习和实践,你将能够构建更加复杂和功能完善的React应用。