React Hooks 最佳实践指南

React Hooks 自 16.8 版本引入以来,已经成为现代 React 开发的标准。本文总结了一些重要的最佳实践。

1. useState 优化

使用函数式更新

// ❌ 避免
setCount(count + 1);

// ✅ 推荐
setCount(prev => prev + 1);

合理拆分状态

// ❌ 避免把所有状态放在一个对象中
const [state, setState] = useState({
  name: '',
  email: '',
  age: 0,
  // ... 更多字段
});

// ✅ 推荐按逻辑分组
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [userInfo, setUserInfo] = useState({ age: 0 });

2. useEffect 最佳实践

正确设置依赖数组

// ❌ 遗漏依赖
useEffect(() => {
  fetchUserData(userId);
}, []); // 缺少 userId 依赖

// ✅ 包含所有依赖
useEffect(() => {
  fetchUserData(userId);
}, [userId]);

清理副作用

useEffect(() => {
  const timer = setInterval(() => {
    // 定时器逻辑
  }, 1000);

  // 清理函数
  return () => clearInterval(timer);
}, []);

3. 自定义 Hooks

提取可复用逻辑

// 自定义 Hook:本地存储
function useLocalStorage(key, initialValue) {
  const [storedValue, setStoredValue] = useState(() => {
    try {
      const item = window.localStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      return initialValue;
    }
  });

  const setValue = (value) => {
    try {
      setStoredValue(value);
      window.localStorage.setItem(key, JSON.stringify(value));
    } catch (error) {
      console.error('Error saving to localStorage:', error);
    }
  };

  return [storedValue, setValue];
}

4. 性能优化

使用 useMemo 和 useCallback

// 缓存计算结果
const expensiveValue = useMemo(() => {
  return heavyCalculation(data);
}, [data]);

// 缓存函数引用
const handleClick = useCallback(() => {
  onItemClick(item.id);
}, [item.id, onItemClick]);

React.memo 配合 Hooks

const MemoizedComponent = React.memo(({ items, onSelect }) => {
  const handleSelect = useCallback((id) => {
    onSelect(id);
  }, [onSelect]);

  return (
    <div>
      {items.map(item => (
        <Item 
          key={item.id} 
          item={item} 
          onSelect={handleSelect} 
        />
      ))}
    </div>
  );
});

5. 常见陷阱

闭包陷阱

// ❌ 问题代码
function Counter() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const timer = setInterval(() => {
      setCount(count + 1); // 总是使用初始值 0
    }, 1000);

    return () => clearInterval(timer);
  }, []);

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

// ✅ 解决方案
function Counter() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const timer = setInterval(() => {
      setCount(prev => prev + 1); // 使用函数式更新
    }, 1000);

    return () => clearInterval(timer);
  }, []);

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

总结

React Hooks 的关键是:

  1. 理解依赖数组的重要性
  2. 合理使用 memo 化技术
  3. 提取可复用的自定义 Hooks
  4. 注意闭包和异步更新的陷阱

掌握这些最佳实践,能让你的 React 应用更加健壮和高效。