技术文档中心
首页
React
Vue
TypeScript
Kotlin
React Native
Electron
Android
首页
React
Vue
TypeScript
Kotlin
React Native
Electron
Android
  • 入门基础

    • React 学习指南
    • React 快速入门
    • 状态管理基础
    • Hooks 基础
    • 组件通信
    • 生命周期与副作用
    • 实战项目
  • 进阶提升

    • Hooks 进阶
    • 组件设计模式
    • 性能优化
    • React Router
    • 表单处理
    • HTTP 请求
  • 状态管理

    • Context API
    • Redux 状态管理
    • Zustand 轻量状态管理
  • 高级主题

    • React + TypeScript
    • React 测试
    • 服务端渲染 (SSR)
    • 微前端架构

状态管理基础

什么是状态

状态(State)是组件的数据,当状态改变时,组件会重新渲染。

import { useState } from 'react';

function Counter() {
  // count 是状态,setCount 是更新状态的函数
  const [count, setCount] = useState(0);
  
  return (
    <div>
      <p>计数: {count}</p>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
}

useState 详解

基本类型状态

function Example() {
  const [text, setText] = useState('');           // 字符串
  const [count, setCount] = useState(0);          // 数字
  const [isOpen, setIsOpen] = useState(false);    // 布尔值
  
  return (
    <div>
      <input value={text} onChange={e => setText(e.target.value)} />
      <p>计数: {count}</p>
      <p>状态: {isOpen ? '开' : '关'}</p>
    </div>
  );
}

对象状态

function UserForm() {
  const [user, setUser] = useState({
    name: '',
    age: 0,
    email: ''
  });
  
  // 更新单个字段
  const updateName = (name) => {
    setUser({ ...user, name });
  };
  
  // 通用更新函数
  const updateField = (field, value) => {
    setUser({ ...user, [field]: value });
  };
  
  return (
    <div>
      <input 
        value={user.name}
        onChange={e => updateField('name', e.target.value)}
        placeholder="姓名"
      />
      <input 
        type="number"
        value={user.age}
        onChange={e => updateField('age', Number(e.target.value))}
        placeholder="年龄"
      />
      <input 
        value={user.email}
        onChange={e => updateField('email', e.target.value)}
        placeholder="邮箱"
      />
      <pre>{JSON.stringify(user, null, 2)}</pre>
    </div>
  );
}

数组状态

function ShoppingList() {
  const [items, setItems] = useState([]);
  const [input, setInput] = useState('');
  
  // 添加项目
  const addItem = () => {
    setItems([...items, { id: Date.now(), name: input }]);
    setInput('');
  };
  
  // 删除项目
  const removeItem = (id) => {
    setItems(items.filter(item => item.id !== id));
  };
  
  // 更新项目
  const updateItem = (id, newName) => {
    setItems(items.map(item => 
      item.id === id ? { ...item, name: newName } : item
    ));
  };
  
  // 清空列表
  const clearAll = () => {
    setItems([]);
  };
  
  return (
    <div>
      <input 
        value={input}
        onChange={e => setInput(e.target.value)}
      />
      <button onClick={addItem}>添加</button>
      <button onClick={clearAll}>清空</button>
      
      <ul>
        {items.map(item => (
          <li key={item.id}>
            {item.name}
            <button onClick={() => removeItem(item.id)}>删除</button>
          </li>
        ))}
      </ul>
    </div>
  );
}

函数式更新

function Counter() {
  const [count, setCount] = useState(0);
  
  // ❌ 可能出问题
  const increment = () => {
    setCount(count + 1);
    setCount(count + 1); // 还是只加 1
  };
  
  // ✅ 正确方式
  const incrementTwice = () => {
    setCount(prev => prev + 1);
    setCount(prev => prev + 1); // 会加 2
  };
  
  return (
    <div>
      <p>计数: {count}</p>
      <button onClick={increment}>错误的 +2</button>
      <button onClick={incrementTwice}>正确的 +2</button>
    </div>
  );
}

惰性初始化

function ExpensiveComponent() {
  // ❌ 每次渲染都会执行
  const [data, setData] = useState(expensiveCalculation());
  
  // ✅ 只在初始化时执行一次
  const [data2, setData2] = useState(() => expensiveCalculation());
  
  return <div>{data}</div>;
}

状态更新原则

1. 不要直接修改状态

function TodoList() {
  const [todos, setTodos] = useState([]);
  
  // ❌ 错误:直接修改
  const addTodo = (text) => {
    todos.push({ id: Date.now(), text });
    setTodos(todos); // 不会触发更新
  };
  
  // ✅ 正确:创建新数组
  const addTodoCorrect = (text) => {
    setTodos([...todos, { id: Date.now(), text }]);
  };
  
  return <div>...</div>;
}

2. 状态更新是异步的

function Counter() {
  const [count, setCount] = useState(0);
  
  const handleClick = () => {
    setCount(count + 1);
    console.log(count); // 还是旧值
    
    // 如果需要使用新值
    setCount(prev => {
      console.log(prev + 1); // 新值
      return prev + 1;
    });
  };
  
  return <button onClick={handleClick}>+1</button>;
}

3. 批量更新

function Form() {
  const [name, setName] = useState('');
  const [age, setAge] = useState(0);
  
  const handleSubmit = () => {
    // React 会批量处理这些更新,只渲染一次
    setName('张三');
    setAge(25);
  };
  
  return <button onClick={handleSubmit}>提交</button>;
}

状态设计原则

1. 最小化状态

// ❌ 不好:冗余状态
function UserProfile() {
  const [firstName, setFirstName] = useState('');
  const [lastName, setLastName] = useState('');
  const [fullName, setFullName] = useState(''); // 冗余
  
  return <div>{fullName}</div>;
}

// ✅ 好:计算派生值
function UserProfile() {
  const [firstName, setFirstName] = useState('');
  const [lastName, setLastName] = useState('');
  const fullName = `${firstName} ${lastName}`; // 直接计算
  
  return <div>{fullName}</div>;
}

2. 避免重复状态

// ❌ 不好:props 复制到 state
function Message({ initialText }) {
  const [text, setText] = useState(initialText);
  // initialText 变化时,text 不会更新
  
  return <div>{text}</div>;
}

// ✅ 好:直接使用 props
function Message({ text }) {
  return <div>{text}</div>;
}

// ✅ 或者使用 key 重置
function Parent() {
  const [text, setText] = useState('hello');
  return <Message key={text} initialText={text} />;
}

3. 扁平化状态

// ❌ 不好:深层嵌套
const [state, setState] = useState({
  user: {
    profile: {
      name: '',
      address: {
        city: '',
        street: ''
      }
    }
  }
});

// ✅ 好:扁平化
const [userName, setUserName] = useState('');
const [city, setCity] = useState('');
const [street, setStreet] = useState('');

多个相关状态

使用 useReducer

import { useReducer } from 'react';

function reducer(state, action) {
  switch (action.type) {
    case 'SET_NAME':
      return { ...state, name: action.payload };
    case 'SET_AGE':
      return { ...state, age: action.payload };
    case 'RESET':
      return { name: '', age: 0 };
    default:
      return state;
  }
}

function Form() {
  const [state, dispatch] = useReducer(reducer, {
    name: '',
    age: 0
  });
  
  return (
    <div>
      <input 
        value={state.name}
        onChange={e => dispatch({ type: 'SET_NAME', payload: e.target.value })}
      />
      <input 
        type="number"
        value={state.age}
        onChange={e => dispatch({ type: 'SET_AGE', payload: Number(e.target.value) })}
      />
      <button onClick={() => dispatch({ type: 'RESET' })}>重置</button>
    </div>
  );
}

实战示例

购物车

import { useState } from 'react';

function ShoppingCart() {
  const [cart, setCart] = useState([]);
  
  const addToCart = (product) => {
    const existing = cart.find(item => item.id === product.id);
    
    if (existing) {
      // 增加数量
      setCart(cart.map(item =>
        item.id === product.id
          ? { ...item, quantity: item.quantity + 1 }
          : item
      ));
    } else {
      // 添加新商品
      setCart([...cart, { ...product, quantity: 1 }]);
    }
  };
  
  const removeFromCart = (id) => {
    setCart(cart.filter(item => item.id !== id));
  };
  
  const updateQuantity = (id, quantity) => {
    if (quantity <= 0) {
      removeFromCart(id);
    } else {
      setCart(cart.map(item =>
        item.id === id ? { ...item, quantity } : item
      ));
    }
  };
  
  const total = cart.reduce((sum, item) => sum + item.price * item.quantity, 0);
  
  return (
    <div>
      <h2>购物车</h2>
      {cart.map(item => (
        <div key={item.id}>
          <span>{item.name}</span>
          <span>¥{item.price}</span>
          <input 
            type="number"
            value={item.quantity}
            onChange={e => updateQuantity(item.id, Number(e.target.value))}
          />
          <button onClick={() => removeFromCart(item.id)}>删除</button>
        </div>
      ))}
      <h3>总计: ¥{total}</h3>
    </div>
  );
}
最近更新: 2026/1/27 15:51
Contributors: hailong
Prev
React 快速入门
Next
Hooks 基础