Skip to content

useState如何更新

在 React 中,useState 是用于在函数组件中添加状态管理的 Hook。更新状态需要使用它返回的 setter 函数,而不是直接修改状态变量。以下是详细说明和示例:


基本用法:

jsx
import React, { useState } from 'react';

function Counter() {
  // 声明状态变量 count 和更新函数 setCount
  const [count, setCount] = useState(0);

  // 正确更新方式:调用 setCount
  const increment = () => {
    setCount(count + 1); // ✅ 直接传递新值
  };

  // 函数式更新(推荐依赖旧值时)
  const incrementSafely = () => {
    setCount(prevCount => prevCount + 1); // ✅ 使用函数确保最新值
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>+1(直接更新)</button>
      <button onClick={incrementSafely}>+1(函数式更新)</button>
    </div>
  );
}

关键规则:

  1. 永远不要直接修改状态

    jsx
    // ❌ 错误!不会触发重新渲染
    count = 10;
  2. 更新对象/数组时需创建新引用

    jsx
    const [user, setUser] = useState({ name: 'Alice', age: 30 });
    
    // ✅ 正确:展开原对象创建新对象
    setUser({ ...user, age: 31 });
    
    // ✅ 数组更新:使用 map/filter/concat 等
    const [list, setList] = useState(['a', 'b']);
    setList([...list, 'c']); // 添加新元素
  3. 异步更新注意
    setCount 是异步的,调用后状态不会立即改变:

    jsx
    console.log(count); // 更新前的旧值
    setCount(42);
    console.log(count); // 仍是旧值!(不是 42)

为什么推荐函数式更新?

当新状态依赖旧值时(尤其是多次连续更新),使用 函数形式 可避免闭包问题:

jsx
// ❌ 连续调用可能不会累加(count 始终是快照值)
const badIncrement = () => {
  setCount(count + 1);
  setCount(count + 1); // 实际只增加一次
};

// ✅ 函数式更新确保基于最新状态
const goodIncrement = () => {
  setCount(prev => prev + 1);
  setCount(prev => prev + 1); // 正确增加两次
};

完整对象更新示例:

jsx
function UserForm() {
  const [form, setForm] = useState({
    name: '',
    email: ''
  });

  const handleChange = (e) => {
    // ✅ 合并更新对象
    setForm({
      ...form,          // 复制旧字段
      [e.target.name]: e.target.value // 覆盖修改的字段
    });
  };

  return (
    <form>
      <input 
        name="name" 
        value={form.name} 
        onChange={handleChange} 
      />
      <input 
        name="email"
        value={form.email} 
        onChange={handleChange} 
      />
    </form>
  );
}

总结:

场景正确做法
更新基本类型(数字/字符串)setValue(newValue)setValue(prev => newValue)
更新对象setObj({ ...obj, key: newValue })
更新数组setArr([...arr, newItem])setArr(arr.filter(...))
连续多次更新依赖旧值必须 用函数式 setValue(prev => prev + 1)

遵循这些规则可确保状态更新触发组件重新渲染,并避免常见的 React 状态管理错误。