React Hooks 的优势和使用场景

62 阅读2分钟
# React Hooks 的优势和使用场景

## 1. 代码复用性提升
**自定义Hook**是Hooks最显著的优势,它允许我们将组件逻辑提取到可重用的函数中。相比传统的HOC或Render Props模式,自定义Hook更加直观且不会增加组件层级。

```jsx
// 自定义Hook示例:使用窗口大小
function useWindowSize() {
  const [size, setSize] = useState({
    width: window.innerWidth,
    height: window.innerHeight
  });

  useEffect(() => {
    const handleResize = () => {
      setSize({
        width: window.innerWidth,
        height: window.innerHeight
      });
    };
    
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);

  return size;
}

// 在组件中使用
function MyComponent() {
  const { width } = useWindowSize();
  return <div>Window width: {width}px</div>;
}

2. 逻辑关注点分离

使用多个useEffect可以按照功能而非生命周期来组织代码,使相关代码保持在一起,提高可维护性。

function UserProfile({ userId }) {
  // 用户数据获取
  const [user, setUser] = useState(null);
  useEffect(() => {
    fetchUser(userId).then(setUser);
  }, [userId]);

  // 用户活动记录
  const [activities, setActivities] = useState([]);
  useEffect(() => {
    fetchActivities(userId).then(setActivities);
  }, [userId]);

  // 相比class组件的分散逻辑,Hooks使相关代码更集中
}

3. 简化复杂组件

useReducer特别适合管理包含多个子值的复杂state逻辑,比useState更适用于复杂的state操作。

function todoReducer(state, action) {
  switch (action.type) {
    case 'add':
      return [...state, action.payload];
    case 'delete':
      return state.filter(todo => todo.id !== action.payload);
    default:
      return state;
  }
}

function TodoList() {
  const [todos, dispatch] = useReducer(todoReducer, []);
  
  const addTodo = text => {
    dispatch({
      type: 'add',
      payload: { id: Date.now(), text }
    });
  };

  // 相比多个useState,useReducer能更好管理复杂状态
}

4. 性能优化

useMemouseCallback可以避免不必要的计算和子组件重渲染。

function ExpensiveComponent({ list }) {
  const sortedList = useMemo(() => {
    return list.sort((a, b) => a.value - b.value);
  }, [list]); // 只有list变化时才重新计算

  const handleClick = useCallback(() => {
    console.log('Item clicked');
  }, []); // 保持函数引用稳定

  return <Child onClick={handleClick} data={sortedList} />;
}

5. 副作用管理

useEffect统一了生命周期方法,提供更清晰的副作用管理方式。

function DataFetcher({ url }) {
  const [data, setData] = useState(null);
  
  useEffect(() => {
    let isMounted = true;
    
    const fetchData = async () => {
      const result = await fetch(url);
      if (isMounted) setData(await result.json());
    };
    
    fetchData();
    
    return () => {
      isMounted = false; // 清理函数避免内存泄漏
    };
  }, [url]); // url变化时重新获取
}

6. 访问Context更简单

useContext让Context的使用更加简洁,无需嵌套Consumer。

const ThemeContext = createContext('light');

function ThemedButton() {
  const theme = useContext(ThemeContext);
  return <button style={{ background: theme }}>按钮</button>;
}

7. 替代class组件

Hooks几乎可以覆盖所有class组件的使用场景,使函数组件成为主流选择。

// 替代componentDidMount
useEffect(() => {
  // 初始化逻辑
}, []);

// 替代componentDidUpdate
useEffect(() => {
  // 更新逻辑
}, [dependencies]);

// 替代componentWillUnmount
useEffect(() => {
  return () => {
    // 清理逻辑
  };
}, []);

8. 更好的TypeScript支持

函数组件配合Hooks能获得更完善的类型推断,减少类型声明代码。