Skip to content

状态更新错误与解决 - React状态管理常见问题完全指南

1. 状态不更新问题

1.1 直接修改状态

jsx
// ❌ 错误: 直接修改状态
function TodoList() {
  const [todos, setTodos] = useState([]);
  
  const addTodo = (text) => {
    // 错误!直接修改了数组
    todos.push({ id: Date.now(), text });
    setTodos(todos);  // React检测不到变化
  };
  
  return (
    <div>
      {todos.map(todo => (
        <div key={todo.id}>{todo.text}</div>
      ))}
      <button onClick={() => addTodo('New Todo')}>Add</button>
    </div>
  );
}

// ✅ 正确: 创建新数组
function TodoListCorrect() {
  const [todos, setTodos] = useState([]);
  
  const addTodo = (text) => {
    // 创建新数组
    setTodos([...todos, { id: Date.now(), text }]);
  };
  
  // 或者使用函数式更新
  const addTodoFunctional = (text) => {
    setTodos(prevTodos => [...prevTodos, { id: Date.now(), text }]);
  };
  
  return (
    <div>
      {todos.map(todo => (
        <div key={todo.id}>{todo.text}</div>
      ))}
      <button onClick={() => addTodo('New Todo')}>Add</button>
    </div>
  );
}

1.2 直接修改对象

jsx
// ❌ 错误: 直接修改对象
function UserProfile() {
  const [user, setUser] = useState({
    name: 'John',
    age: 25,
    address: {
      city: 'Beijing',
      street: '123 Main St'
    }
  });
  
  const updateCity = (newCity) => {
    // 错误!直接修改了嵌套对象
    user.address.city = newCity;
    setUser(user);  // React检测不到变化
  };
  
  return (
    <div>
      <p>{user.name} lives in {user.address.city}</p>
      <button onClick={() => updateCity('Shanghai')}>Move to Shanghai</button>
    </div>
  );
}

// ✅ 正确: 创建新对象
function UserProfileCorrect() {
  const [user, setUser] = useState({
    name: 'John',
    age: 25,
    address: {
      city: 'Beijing',
      street: '123 Main St'
    }
  });
  
  const updateCity = (newCity) => {
    // 创建新对象,保持不可变性
    setUser({
      ...user,
      address: {
        ...user.address,
        city: newCity
      }
    });
  };
  
  // 或者使用Immer库简化
  const updateCityWithImmer = (newCity) => {
    setUser(produce(draft => {
      draft.address.city = newCity;
    }));
  };
  
  return (
    <div>
      <p>{user.name} lives in {user.address.city}</p>
      <button onClick={() => updateCity('Shanghai')}>Move to Shanghai</button>
    </div>
  );
}

1.3 状态批量更新问题

jsx
// ❌ 错误: 依赖当前状态的多次更新
function Counter() {
  const [count, setCount] = useState(0);
  
  const increment3Times = () => {
    // 错误!所有更新都基于相同的count值
    setCount(count + 1);  // count = 0, 设置为1
    setCount(count + 1);  // count = 0, 设置为1
    setCount(count + 1);  // count = 0, 设置为1
    // 结果: count = 1 (而不是3)
  };
  
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment3Times}>+3</button>
    </div>
  );
}

// ✅ 正确: 使用函数式更新
function CounterCorrect() {
  const [count, setCount] = useState(0);
  
  const increment3Times = () => {
    // 使用函数式更新,每次都基于最新值
    setCount(prevCount => prevCount + 1);  // 0 -> 1
    setCount(prevCount => prevCount + 1);  // 1 -> 2
    setCount(prevCount => prevCount + 1);  // 2 -> 3
    // 结果: count = 3
  };
  
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment3Times}>+3</button>
    </div>
  );
}

2. 闭包陷阱

2.1 useEffect中的闭包问题

jsx
// ❌ 错误: 定时器中的闭包
function Timer() {
  const [count, setCount] = useState(0);
  
  useEffect(() => {
    // count被"困在"初始值0
    const timer = setInterval(() => {
      console.log(count);  // 始终输出0
      setCount(count + 1);  // 始终是0 + 1
    }, 1000);
    
    return () => clearInterval(timer);
  }, []);  // 空依赖数组导致闭包问题
  
  return <div>Count: {count}</div>;
}

// ✅ 解决方案1: 添加依赖
function TimerSolution1() {
  const [count, setCount] = useState(0);
  
  useEffect(() => {
    const timer = setInterval(() => {
      console.log(count);
      setCount(count + 1);
    }, 1000);
    
    return () => clearInterval(timer);
  }, [count]);  // 添加count依赖
  
  return <div>Count: {count}</div>;
}

// ✅ 解决方案2: 使用函数式更新
function TimerSolution2() {
  const [count, setCount] = useState(0);
  
  useEffect(() => {
    const timer = setInterval(() => {
      // 使用函数式更新,不依赖外部count
      setCount(prevCount => {
        console.log(prevCount);
        return prevCount + 1;
      });
    }, 1000);
    
    return () => clearInterval(timer);
  }, []);  // 空依赖数组也能正常工作
  
  return <div>Count: {count}</div>;
}

// ✅ 解决方案3: 使用useRef
function TimerSolution3() {
  const [count, setCount] = useState(0);
  const countRef = useRef(count);
  
  // 保持ref同步
  useEffect(() => {
    countRef.current = count;
  }, [count]);
  
  useEffect(() => {
    const timer = setInterval(() => {
      console.log(countRef.current);
      setCount(countRef.current + 1);
    }, 1000);
    
    return () => clearInterval(timer);
  }, []);
  
  return <div>Count: {count}</div>;
}

2.2 事件处理器中的闭包

jsx
// ❌ 错误: 延迟执行时的闭包
function SearchInput() {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState([]);
  
  const search = () => {
    // query被"困在"点击时的值
    setTimeout(() => {
      console.log('Searching for:', query);
      // 如果在3秒内多次点击,query可能不是最新的
      fetch(`/api/search?q=${query}`)
        .then(res => res.json())
        .then(setResults);
    }, 3000);
  };
  
  return (
    <div>
      <input value={query} onChange={e => setQuery(e.target.value)} />
      <button onClick={search}>Search</button>
      {results.map(r => <div key={r.id}>{r.title}</div>)}
    </div>
  );
}

// ✅ 正确: 使用useRef或useCallback
function SearchInputCorrect() {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState([]);
  const queryRef = useRef(query);
  
  useEffect(() => {
    queryRef.current = query;
  }, [query]);
  
  const search = () => {
    setTimeout(() => {
      // 使用ref获取最新值
      console.log('Searching for:', queryRef.current);
      fetch(`/api/search?q=${queryRef.current}`)
        .then(res => res.json())
        .then(setResults);
    }, 3000);
  };
  
  return (
    <div>
      <input value={query} onChange={e => setQuery(e.target.value)} />
      <button onClick={search}>Search</button>
      {results.map(r => <div key={r.id}>{r.title}</div>)}
    </div>
  );
}

3. 异步状态更新问题

3.1 状态更新后立即读取

jsx
// ❌ 错误: 期望立即读取新状态
function Form() {
  const [formData, setFormData] = useState({ name: '', email: '' });
  
  const handleSubmit = () => {
    setFormData({ name: 'John', email: 'john@example.com' });
    
    // 错误!这里formData仍是旧值
    console.log(formData);  // { name: '', email: '' }
    
    // 使用旧值发送请求
    sendToServer(formData);  // 发送的是旧数据!
  };
  
  return (
    <form>
      <input value={formData.name} onChange={e => setFormData({...formData, name: e.target.value})} />
      <input value={formData.email} onChange={e => setFormData({...formData, email: e.target.value})} />
      <button type="button" onClick={handleSubmit}>Submit</button>
    </form>
  );
}

// ✅ 正确: 使用局部变量或useEffect
function FormCorrect() {
  const [formData, setFormData] = useState({ name: '', email: '' });
  
  const handleSubmit = () => {
    const newData = { name: 'John', email: 'john@example.com' };
    setFormData(newData);
    
    // 使用局部变量
    console.log(newData);
    sendToServer(newData);
  };
  
  // 或者使用useEffect监听状态变化
  const handleSubmitWithEffect = () => {
    setFormData({ name: 'John', email: 'john@example.com' });
  };
  
  useEffect(() => {
    if (formData.name && formData.email) {
      console.log(formData);
      sendToServer(formData);
    }
  }, [formData]);
  
  return (
    <form>
      <input value={formData.name} onChange={e => setFormData({...formData, name: e.target.value})} />
      <input value={formData.email} onChange={e => setFormData({...formData, email: e.target.value})} />
      <button type="button" onClick={handleSubmit}>Submit</button>
    </form>
  );
}

3.2 竞态条件

jsx
// ❌ 错误: 未处理的竞态条件
function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  
  useEffect(() => {
    // 如果userId快速变化,可能导致竞态
    fetchUser(userId).then(data => {
      // 可能设置的是旧userId的数据
      setUser(data);
    });
  }, [userId]);
  
  return user ? <div>{user.name}</div> : <div>Loading...</div>;
}

// ✅ 正确: 使用cleanup取消过期请求
function UserProfileCorrect({ userId }) {
  const [user, setUser] = useState(null);
  
  useEffect(() => {
    let cancelled = false;
    
    fetchUser(userId).then(data => {
      // 只有未取消才更新状态
      if (!cancelled) {
        setUser(data);
      }
    });
    
    return () => {
      cancelled = true;
    };
  }, [userId]);
  
  return user ? <div>{user.name}</div> : <div>Loading...</div>;
}

// ✅ 更好: 使用AbortController
function UserProfileBetter({ userId }) {
  const [user, setUser] = useState(null);
  
  useEffect(() => {
    const abortController = new AbortController();
    
    fetch(`/api/users/${userId}`, {
      signal: abortController.signal
    })
      .then(res => res.json())
      .then(data => setUser(data))
      .catch(error => {
        if (error.name !== 'AbortError') {
          console.error(error);
        }
      });
    
    return () => {
      abortController.abort();
    };
  }, [userId]);
  
  return user ? <div>{user.name}</div> : <div>Loading...</div>;
}

4. 派生状态问题

4.1 不必要的状态同步

jsx
// ❌ 错误: 将props复制到state
function EmailInput({ defaultEmail }) {
  const [email, setEmail] = useState(defaultEmail);
  
  // 错误!props变化时state不会更新
  return (
    <input 
      value={email} 
      onChange={e => setEmail(e.target.value)} 
    />
  );
}

// ✅ 解决方案1: 完全受控组件
function EmailInputControlled({ email, onChange }) {
  return (
    <input 
      value={email} 
      onChange={e => onChange(e.target.value)} 
    />
  );
}

// ✅ 解决方案2: 使用key重置组件
function ParentComponent() {
  const [email, setEmail] = useState('john@example.com');
  
  return (
    <div>
      <button onClick={() => setEmail('jane@example.com')}>Change Email</button>
      {/* key变化会重新创建组件 */}
      <EmailInput key={email} defaultEmail={email} />
    </div>
  );
}

// ✅ 解决方案3: 使用useEffect同步
function EmailInputWithSync({ defaultEmail }) {
  const [email, setEmail] = useState(defaultEmail);
  
  useEffect(() => {
    setEmail(defaultEmail);
  }, [defaultEmail]);
  
  return (
    <input 
      value={email} 
      onChange={e => setEmail(e.target.value)} 
    />
  );
}

// ✅ 解决方案4: 派生状态(最佳)
function EmailInputDerived({ defaultEmail }) {
  const [emailDraft, setEmailDraft] = useState('');
  const [isEditing, setIsEditing] = useState(false);
  
  // 派生最终显示的email
  const displayEmail = isEditing ? emailDraft : defaultEmail;
  
  const handleFocus = () => {
    setIsEditing(true);
    setEmailDraft(defaultEmail);
  };
  
  const handleBlur = () => {
    setIsEditing(false);
  };
  
  return (
    <input 
      value={displayEmail} 
      onChange={e => setEmailDraft(e.target.value)}
      onFocus={handleFocus}
      onBlur={handleBlur}
    />
  );
}

4.2 计算状态应该派生

jsx
// ❌ 错误: 冗余状态
function FilteredList({ items }) {
  const [filter, setFilter] = useState('');
  const [filteredItems, setFilteredItems] = useState(items);
  
  useEffect(() => {
    // 维护两个相关状态很容易出错
    const filtered = items.filter(item => 
      item.name.includes(filter)
    );
    setFilteredItems(filtered);
  }, [items, filter]);
  
  return (
    <div>
      <input value={filter} onChange={e => setFilter(e.target.value)} />
      {filteredItems.map(item => (
        <div key={item.id}>{item.name}</div>
      ))}
    </div>
  );
}

// ✅ 正确: 派生状态
function FilteredListCorrect({ items }) {
  const [filter, setFilter] = useState('');
  
  // 直接计算,无需额外状态
  const filteredItems = useMemo(() => {
    return items.filter(item => 
      item.name.includes(filter)
    );
  }, [items, filter]);
  
  return (
    <div>
      <input value={filter} onChange={e => setFilter(e.target.value)} />
      {filteredItems.map(item => (
        <div key={item.id}>{item.name}</div>
      ))}
    </div>
  );
}

5. Context更新问题

5.1 Context导致的重渲染

jsx
// ❌ 错误: Context值每次都是新对象
function AppProvider({ children }) {
  const [user, setUser] = useState(null);
  const [theme, setTheme] = useState('light');
  
  // 每次渲染都创建新对象!
  const value = {
    user,
    setUser,
    theme,
    setTheme
  };
  
  return (
    <AppContext.Provider value={value}>
      {children}
    </AppContext.Provider>
  );
}

// ✅ 正确: 使用useMemo缓存
function AppProviderCorrect({ children }) {
  const [user, setUser] = useState(null);
  const [theme, setTheme] = useState('light');
  
  // 只有依赖变化时才创建新对象
  const value = useMemo(() => ({
    user,
    setUser,
    theme,
    setTheme
  }), [user, theme]);
  
  return (
    <AppContext.Provider value={value}>
      {children}
    </AppContext.Provider>
  );
}

// ✅ 更好: 拆分Context
function AppProviderBetter({ children }) {
  const [user, setUser] = useState(null);
  const [theme, setTheme] = useState('light');
  
  const userValue = useMemo(() => ({ user, setUser }), [user]);
  const themeValue = useMemo(() => ({ theme, setTheme }), [theme]);
  
  return (
    <UserContext.Provider value={userValue}>
      <ThemeContext.Provider value={themeValue}>
        {children}
      </ThemeContext.Provider>
    </UserContext.Provider>
  );
}

5.2 Context消费组件的优化

jsx
// ❌ 错误: 整个组件重渲染
function UserDisplay() {
  const { user, theme } = useContext(AppContext);
  
  // 即使只用user,theme变化也会重渲染
  return <div>{user?.name}</div>;
}

// ✅ 正确: 使用React.memo
const UserDisplay = React.memo(function UserDisplay() {
  const { user } = useContext(AppContext);
  return <div>{user?.name}</div>;
});

// ✅ 更好: 拆分Context
function UserDisplay() {
  const { user } = useContext(UserContext);  // 只订阅user
  return <div>{user?.name}</div>;
}

// ✅ 最佳: 使用selector
function UserDisplay() {
  // 使用第三方库如use-context-selector
  const user = useContextSelector(AppContext, ctx => ctx.user);
  return <div>{user?.name}</div>;
}

6. 状态初始化问题

6.1 复杂初始化

jsx
// ❌ 错误: 每次渲染都执行复杂计算
function ExpensiveComponent() {
  // 每次渲染都执行,即使只需要一次
  const [data, setData] = useState(expensiveComputation());
  
  return <div>{data}</div>;
}

// ✅ 正确: 使用惰性初始化
function ExpensiveComponentCorrect() {
  // 函数只在首次渲染时执行
  const [data, setData] = useState(() => {
    console.log('Computing initial state...');
    return expensiveComputation();
  });
  
  return <div>{data}</div>;
}

// ✅ 示例: 从localStorage初始化
function usePersistedState(key, defaultValue) {
  const [state, setState] = useState(() => {
    // 只在mount时读取localStorage
    const stored = localStorage.getItem(key);
    return stored ? JSON.parse(stored) : defaultValue;
  });
  
  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(state));
  }, [key, state]);
  
  return [state, setState];
}

6.2 异步初始化

jsx
// ❌ 错误: 在useState中使用异步函数
function UserProfile() {
  // 错误!useState不支持异步初始化
  const [user, setUser] = useState(async () => {
    const res = await fetch('/api/user');
    return res.json();
  });
  
  return <div>{user?.name}</div>;
}

// ✅ 正确: 使用useEffect
function UserProfileCorrect() {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);
  
  useEffect(() => {
    let cancelled = false;
    
    fetch('/api/user')
      .then(res => res.json())
      .then(data => {
        if (!cancelled) {
          setUser(data);
          setLoading(false);
        }
      });
    
    return () => {
      cancelled = true;
    };
  }, []);
  
  if (loading) return <div>Loading...</div>;
  return <div>{user?.name}</div>;
}

7. 状态共享问题

7.1 状态提升过度

jsx
// ❌ 不好: 过度提升状态
function App() {
  // 所有状态都在顶层,导致不必要的重渲染
  const [sidebar, setSidebar] = useState({ open: false });
  const [modal, setModal] = useState({ open: false });
  const [form, setForm] = useState({ name: '', email: '' });
  const [list, setList] = useState([]);
  
  return (
    <div>
      <Sidebar sidebar={sidebar} setSidebar={setSidebar} />
      <Modal modal={modal} setModal={setModal} />
      <Form form={form} setForm={setForm} />
      <List list={list} setList={setList} />
    </div>
  );
}

// ✅ 更好: 状态就近管理
function App() {
  const [list, setList] = useState([]);  // 只提升真正需要共享的
  
  return (
    <div>
      <Sidebar />  {/* 内部管理自己的状态 */}
      <Modal />
      <Form onSubmit={data => setList([...list, data])} />
      <List list={list} />
    </div>
  );
}

function Sidebar() {
  const [open, setOpen] = useState(false);  // 局部状态
  
  return (
    <div className={open ? 'open' : ''}>
      <button onClick={() => setOpen(!open)}>Toggle</button>
    </div>
  );
}

7.2 使用Composition避免prop drilling

jsx
// ❌ 不好: Prop drilling
function App() {
  const [user, setUser] = useState(null);
  
  return <Layout user={user} setUser={setUser} />;
}

function Layout({ user, setUser }) {
  return (
    <div>
      <Header user={user} setUser={setUser} />
      <Content user={user} />
    </div>
  );
}

function Header({ user, setUser }) {
  return <UserMenu user={user} setUser={setUser} />;
}

function UserMenu({ user, setUser }) {
  return (
    <div>
      {user ? (
        <button onClick={() => setUser(null)}>Logout</button>
      ) : (
        <button onClick={() => setUser({ name: 'John' })}>Login</button>
      )}
    </div>
  );
}

// ✅ 更好: 使用Composition
function App() {
  const [user, setUser] = useState(null);
  
  return (
    <Layout
      header={<UserMenu user={user} setUser={setUser} />}
      content={<Content user={user} />}
    />
  );
}

function Layout({ header, content }) {
  return (
    <div>
      <Header>{header}</Header>
      <main>{content}</main>
    </div>
  );
}

function Header({ children }) {
  return <header>{children}</header>;
}

8. useReducer替代useState

8.1 复杂状态逻辑

jsx
// ❌ 复杂: 多个相关状态
function Form() {
  const [values, setValues] = useState({});
  const [errors, setErrors] = useState({});
  const [touched, setTouched] = useState({});
  const [isSubmitting, setIsSubmitting] = useState(false);
  
  const handleChange = (name, value) => {
    setValues({ ...values, [name]: value });
    setErrors({ ...errors, [name]: validate(name, value) });
  };
  
  const handleBlur = (name) => {
    setTouched({ ...touched, [name]: true });
  };
  
  const handleSubmit = async () => {
    setIsSubmitting(true);
    // ...
    setIsSubmitting(false);
  };
  
  return (/* ... */);
}

// ✅ 更好: 使用useReducer
function formReducer(state, action) {
  switch (action.type) {
    case 'CHANGE':
      return {
        ...state,
        values: { ...state.values, [action.name]: action.value },
        errors: { ...state.errors, [action.name]: validate(action.name, action.value) }
      };
    
    case 'BLUR':
      return {
        ...state,
        touched: { ...state.touched, [action.name]: true }
      };
    
    case 'SUBMIT_START':
      return { ...state, isSubmitting: true };
    
    case 'SUBMIT_SUCCESS':
      return {
        ...state,
        isSubmitting: false,
        values: {},
        errors: {},
        touched: {}
      };
    
    case 'SUBMIT_ERROR':
      return {
        ...state,
        isSubmitting: false,
        errors: action.errors
      };
    
    default:
      return state;
  }
}

function FormWithReducer() {
  const [state, dispatch] = useReducer(formReducer, {
    values: {},
    errors: {},
    touched: {},
    isSubmitting: false
  });
  
  const handleChange = (name, value) => {
    dispatch({ type: 'CHANGE', name, value });
  };
  
  const handleBlur = (name) => {
    dispatch({ type: 'BLUR', name });
  };
  
  const handleSubmit = async () => {
    dispatch({ type: 'SUBMIT_START' });
    try {
      await submitForm(state.values);
      dispatch({ type: 'SUBMIT_SUCCESS' });
    } catch (errors) {
      dispatch({ type: 'SUBMIT_ERROR', errors });
    }
  };
  
  return (/* ... */);
}

9. 调试工具和技巧

9.1 React DevTools

jsx
// 使用React DevTools查看状态
function DebuggableComponent() {
  const [count, setCount] = useState(0);
  const [user, setUser] = useState({ name: 'John' });
  
  // 在DevTools中可以看到所有state
  // 还可以手动修改state进行测试
  
  return (
    <div>
      <p>Count: {count}</p>
      <p>User: {user.name}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

9.2 自定义调试Hook

jsx
// 监控状态变化
function useStateWithLog(initialValue, name) {
  const [value, setValue] = useState(initialValue);
  
  useEffect(() => {
    console.log(`[${name}] changed to:`, value);
  }, [value, name]);
  
  return [value, setValue];
}

// 使用
function Component() {
  const [count, setCount] = useStateWithLog(0, 'count');
  return <button onClick={() => setCount(count + 1)}>{count}</button>;
}

// 追踪重渲染原因
function useWhyDidYouUpdate(name, props) {
  const previousProps = useRef();
  
  useEffect(() => {
    if (previousProps.current) {
      const allKeys = Object.keys({ ...previousProps.current, ...props });
      const changesObj = {};
      
      allKeys.forEach(key => {
        if (previousProps.current[key] !== props[key]) {
          changesObj[key] = {
            from: previousProps.current[key],
            to: props[key]
          };
        }
      });
      
      if (Object.keys(changesObj).length > 0) {
        console.log('[why-did-you-update]', name, changesObj);
      }
    }
    
    previousProps.current = props;
  });
}

// 使用
function MyComponent(props) {
  useWhyDidYouUpdate('MyComponent', props);
  return <div>{props.value}</div>;
}

10. 最佳实践总结

10.1 状态管理清单

typescript
const stateManagementChecklist = [
  '✅ 保持状态不可变性',
  '✅ 使用函数式更新处理依赖当前状态的更新',
  '✅ 避免在useState中直接修改对象/数组',
  '✅ 注意闭包陷阱,特别是在useEffect和事件处理器中',
  '✅ 处理异步操作的竞态条件',
  '✅ 优先使用派生状态而不是冗余状态',
  '✅ 合理拆分和提升状态',
  '✅ 使用Context时注意性能优化',
  '✅ 复杂状态逻辑考虑使用useReducer',
  '✅ 使用调试工具定位问题'
];

10.2 常见错误速查

typescript
const commonErrors = {
  '状态不更新': {
    原因: ['直接修改状态', '对象引用相同'],
    解决: ['创建新对象/数组', '使用展开运算符或Immer']
  },
  
  '闭包陷阱': {
    原因: ['useEffect依赖缺失', '定时器/事件处理器中的闭包'],
    解决: ['添加依赖', '使用函数式更新', '使用useRef']
  },
  
  '异步问题': {
    原因: ['setState后立即读取', '竞态条件'],
    解决: ['使用局部变量', '使用cleanup', '使用AbortController']
  },
  
  '性能问题': {
    原因: ['Context重渲染', '过度状态提升', '计算状态未优化'],
    解决: ['useMemo缓存Context', '状态下放', '使用useMemo']
  }
};

11. 总结

React状态更新错误的核心要点:

  1. 不可变性: 永远不要直接修改状态
  2. 函数式更新: 依赖当前状态时使用函数式更新
  3. 闭包理解: 理解并避免闭包陷阱
  4. 异步处理: 正确处理异步状态更新
  5. 派生状态: 优先派生而不是同步
  6. Context优化: 注意Context导致的性能问题
  7. 合理选择: useState vs useReducer
  8. 调试工具: 善用DevTools和自定义Hook
  9. 性能考虑: 避免不必要的重渲染
  10. 最佳实践: 遵循React官方建议

掌握这些知识可以避免大部分React状态管理的常见错误,写出更健壮的React应用。