Back to Blog
· 4 min read

React 状态管理

React

随着应用规模增长,状态管理极易变得越来越混乱。

React 状态管理是应用架构的核心,良好的状态管理能让代码更清晰、维护更轻松。

1. React 内置状态管理

1.1 useState:局部状态

function Counter() {
  const [count, setCount] = useState(0);
  const [user, setUser] = useState({ name: '张三', age: 25 });

  return (
    <div>
      <p>计数: {count}</p>
      <button onClick={() => setCount(c => c + 1)}>增加</button>
      <button onClick={() => setUser({ ...user, age: user.age + 1 })}>长大</button>
    </div>
  );
}

1.2 useReducer:复杂状态

function todoReducer(state, action) {
  switch (action.type) {
    case 'ADD':
      return [...state, action.payload];
    case 'TOGGLE':
      return state.map(todo =>
        todo.id === action.payload ? { ...todo, done: !todo.done } : todo
      );
    case 'DELETE':
      return state.filter(todo => todo.id !== action.payload);
    default:
      return state;
  }
}

function TodoApp() {
  const [todos, dispatch] = useReducer(todoReducer, []);

  return (
    <div>
      <button onClick={() => dispatch({ type: 'ADD', payload: { id: Date.now(), text: '新任务', done: false }})}>
        添加
      </button>
    </div>
  );
}

1.3 Context:跨组件共享

const ThemeContext = createContext();
const UserContext = createContext();

function App() {
  const [theme, setTheme] = useState('light');
  const [user, setUser] = useState({ name: '张三', id: 1 });

  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      <UserContext.Provider value={user}>
        <Layout />
      </UserContext.Provider>
    </ThemeContext.Provider>
  );
}

function Layout() {
  const { theme, setTheme } = useContext(ThemeContext);
  const user = useContext(UserContext);

  return (
    <div className={theme}>
      <h1>欢迎, {user.name}</h1>
      <button onClick={() => setTheme(t => t === 'light' ? 'dark' : 'light')}>
        切换主题
      </button>
    </div>
  );
}

2. 状态管理最佳实践

2.1 最小化状态

// ❌ 避免:冗余状态
function BadExample() {
  const [firstName, setFirstName] = useState('张');
  const [lastName, setLastName] = useState('三');
  const fullName = firstName + lastName; // 这不需要是状态

  return <div>{fullName}</div>;
}

// ✅ 推荐:计算属性
function GoodExample() {
  const [user, setUser] = useState({ firstName: '张', lastName: '三' });
  const fullName = `${user.firstName}${user.lastName}`; // 通过计算得到

  return <div>{fullName}</div>;
}

2.2 状态提升

// ❌ 避免:状态分散
function Parent() {
  return (
    <>
      <ChildA />
      <ChildB />
    </>
  );
}

// ✅ 推荐:提升到共同父组件
function Parent() {
  const [shared, setShared] = useState('');

  return (
    <>
      <ChildA value={shared} onChange={setShared} />
      <ChildB value={shared} />
    </>
  );
}

2.3 不可变数据

// ❌ 避免:直接修改状态
function badReducer(state, action) {
  switch (action.type) {
    case 'ADD':
      state.push(action.payload); // 直接修改!
      return state;
  }
}

// ✅ 推荐:创建新数据
function goodReducer(state, action) {
  switch (action.type) {
    case 'ADD':
      return [...state, action.payload]; // 新数组
    case 'UPDATE':
      return state.map(item =>
        item.id === action.payload.id ? { ...item, ...action.payload } : item
      );
  }
}

3. 第三方状态管理

3.1 Redux

// store.js
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './counterSlice';

export const store = configureStore({
  reducer: {
    counter: counterReducer,
  },
});

// counterSlice.js
import { createSlice } from '@reduxjs/toolkit';

const counterSlice = createSlice({
  name: 'counter',
  initialState: { value: 0 },
  reducers: {
    increment: (state) => { state.value += 1; },
    decrement: (state) => { state.value -= 1; },
    incrementByAmount: (state, action) => {
      state.value += action.payload;
    },
  },
});

export const { increment, decrement, incrementByAmount } = counterSlice.actions;
export default counterSlice.reducer;

// Component.jsx
import { useSelector, useDispatch } from 'react-redux';
import { increment } from './counterSlice';

function Counter() {
  const count = useSelector(state => state.counter.value);
  const dispatch = useDispatch();

  return (
    <div>
      <p>计数: {count}</p>
      <button onClick={() => dispatch(increment())}>增加</button>
    </div>
  );
}

3.2 Zustand(轻量级)

import { create } from 'zustand';

const useStore = create(set => ({
  count: 0,
  increment: () => set(state => ({ count: state.count + 1 })),
  decrement: () => set(state => ({ count: state.count - 1 })),
}));

function Counter() {
  const { count, increment, decrement } = useStore();

  return (
    <div>
      <p>计数: {count}</p>
      <button onClick={decrement}>减少</button>
      <button onClick={increment}>增加</button>
    </div>
  );
}

3.3 方案对比

方案优点缺点适用场景
useState简单、无依赖状态分散小型应用
useReducer逻辑集中学习成本中型应用
Context跨组件共享容易过度使用全局配置
Redux强大工具链样板代码多大型应用
Zustand轻量简单社区较小中小型应用

4. 状态管理模式

4.1 原子化状态(Jotai)

import { atom } from 'jotai';
import { useAtom } from 'jotai';

const countAtom = atom(0);
const doubledAtom = atom((get) => get(countAtom) * 2);

function Counter() {
  const [count, setCount] = useAtom(countAtom);
  const [doubled] = useAtom(doubledAtom);

  return (
    <div>
      <p>计数: {count}</p>
      <p>翻倍: {doubled}</p>
      <button onClick={() => setCount(c => c + 1)}>增加</button>
    </div>
  );
}

4.2 信号(Signals)

import { signal, computed } from '@preact/signals-react';

const count = signal(0);
const doubled = computed(() => count.value * 2);

function Counter() {
  return (
    <div>
      <p>计数: {count}</p>
      <p>翻倍: {doubled}</p>
      <button onClick={() => count.value++}>增加</button>
    </div>
  );
}

5. 总结

选择状态管理方案的建议:

  • 小型应用: useState + useReducer 足够
  • 中型应用: Context + 自定义 Hook,或 Zustand
  • 大型应用: Redux Toolkit 或其他成熟方案

核心原则:最小化状态、单一数据源、不可变更新。


相关阅读