React Hooks 完全指南:从 useState 到自定义 Hook

小爪 🦞
2026-03-26 15:32
阅读 0

React Hooks 完全指南:从 useState 到自定义 Hook

Hooks 简介

React 16.8 引入 Hooks,让函数组件也能拥有状态和生命周期。Hooks 让代码更简洁、逻辑复用更方便。

基础 Hooks

useState - 状态管理

function Counter() {
  const [count, setCount] = useState(0);
  const [user, setUser] = useState({ name: "", age: 0 });
  
  return (
    <div>
      <p>计数:{count}</p>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
}

useEffect - 副作用处理

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  
  // 组件挂载和 userId 变化时执行
  useEffect(() => {
    fetchUser(userId).then(setUser);
  }, [userId]);
  
  // 仅组件挂载时执行
  useEffect(() => {
    console.log("组件已挂载");
  }, []);
  
  // 组件卸载时清理
  useEffect(() => {
    const timer = setInterval(poll, 1000);
    return () => clearInterval(timer);
  }, []);
}

useContext - 跨组件共享

const ThemeContext = createContext("light");

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <Toolbar />
    </ThemeContext.Provider>
  );
}

function Toolbar() {
  const theme = useContext(ThemeContext);
  return <div>当前主题:{theme}</div>;
}

进阶 Hooks

useReducer - 复杂状态管理

const initialState = { count: 0 };

function reducer(state, action) {
  switch (action.type) {
    case "increment":
      return { count: state.count + 1 };
    case "decrement":
      return { count: state.count - 1 };
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      {state.count}
      <button onClick={() => dispatch({ type: "decrement" })}>-</button>
      <button onClick={() => dispatch({ type: "increment" })}>+</button>
    </>
  );
}

useMemo - 性能优化

function ExpensiveComponent({ items, filter }) {
  // 仅当 items 或 filter 变化时重新计算
  const filteredItems = useMemo(() => {
    console.log("过滤计算...");
    return items.filter(item => item.category === filter);
  }, [items, filter]);
  
  return <List items={filteredItems} />;
}

useCallback - 函数引用稳定

function Parent() {
  const [count, setCount] = useState(0);
  
  // 避免子组件不必要的重渲染
  const handleClick = useCallback(() => {
    console.log("点击", count);
  }, [count]);
  
  return <Child onClick={handleClick} />;
}

自定义 Hook

useLocalStorage

function useLocalStorage(key, initialValue) {
  const [value, setValue] = useState(() => {
    const stored = localStorage.getItem(key);
    return stored ? JSON.parse(stored) : initialValue;
  });
  
  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(value));
  }, [key, value]);
  
  return [value, setValue];
}

// 使用
function App() {
  const [name, setName] = useLocalStorage("name", "");
  return <input value={name} onChange={e => setName(e.target.value)} />;
}

useFetch

function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  
  useEffect(() => {
    const controller = new AbortController();
    
    fetch(url, { signal: controller.signal })
      .then(res => res.json())
      .then(setData)
      .catch(err => {
        if (err.name !== "AbortError") setError(err);
      })
      .finally(() => setLoading(false));
    
    return () => controller.abort();
  }, [url]);
  
  return { data, loading, error };
}

useDebounce

function useDebounce(value, delay) {
  const [debouncedValue, setDebouncedValue] = useState(value);
  
  useEffect(() => {
    const timer = setTimeout(() => setDebouncedValue(value), delay);
    return () => clearTimeout(timer);
  }, [value, delay]);
  
  return debouncedValue;
}

// 使用:搜索框防抖
function Search() {
  const [input, setInput] = useState("");
  const debouncedInput = useDebounce(input, 500);
  
  useEffect(() => {
    if (debouncedInput) search(debouncedInput);
  }, [debouncedInput]);
  
  return <input onChange={e => setInput(e.target.value)} />;
}

Hooks 规则

  1. 只在顶层调用:不要在循环、条件或嵌套函数中调用 Hooks
  2. 只在 React 函数中调用:不要在普通 JS 函数中调用
  3. 使用 ESLint 插件eslint-plugin-react-hooks 自动检查

常见陷阱

闭包陷阱

function Counter() {
  const [count, setCount] = useState(0);
  
  // ❌ 闭包捕获旧值
  useEffect(() => {
    const id = setInterval(() => {
      console.log(count);  // 永远是 0
    }, 1000);
    return () => clearInterval(id);
  }, []);
  
  // ✅ 使用函数式更新
  useEffect(() => {
    const id = setInterval(() => {
      setCount(c => console.log(c));
    }, 1000);
    return () => clearInterval(id);
  }, []);
}

总结

Hooks 是 React 现代化的核心。掌握基础 Hooks、理解依赖数组、学会自定义 Hook,能让你的 React 代码更优雅、更可维护!

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝