🚀 从 "bug 缠身" 到 "代码大神":小李的 React Hooks 救赎记

79 阅读4分钟

第一章:计数器的 "诡异行为"😫

"这不可能!" 小李盯着屏幕上的计数器,头发都快被抓秃了。

他刚写了个简单的计数器组件,按钮上明明写着 "+3",可点击后数字却只加 1。代码长这样:

const [count, setCount] = useState(0);
const handleClick = () => {
  setCount(count + 1);
  setCount(count + 1);
  setCount(count + 1); // 本以为会+3,结果只+1?
};

小李拍了拍键盘,怀疑是电脑出了问题。他又点了几次按钮,数字依然固执地 "1、2、3..." 缓慢增长。"难道 React 跟我作对?" 他瘫在椅子上,眼神空洞🤔。

第二章:useState 的 "秘密协议"😎

就在小李快要放弃时,前辈王哥路过:"咋了?被 React 按在地上摩擦了?"

听小李说完困惑,王哥笑了:"这是 useState 的 ' 异步小脾气 '!setState 是异步的,React 会合并多次更新,避免频繁渲染。你三次调用 setCount 时,用的都是同一个初始 count 值,相当于只执行了一次 + 1。"

王哥拿起笔,划掉原来的代码,写下新方案:

const handleClick = () => {
  // 函数式更新:每次都基于上一个最新状态计算
  setCount(prev => prev + 1);
  setCount(prev => prev + 1);
  setCount(prev => prev + 1); // 这下真·+3了!
};

点击按钮,数字果然从 0 跳到 3!小李眼睛一亮,仿佛打开了新世界的大门🎉。原来 useState 的更新是 "批量处理" 的,函数式更新能保证每次都拿到最新状态 —— 这就是它的 "秘密协议"。

第三章:主题切换的 "千层套路"😵

解决了计数器问题,小李信心大增,又接手了一个 "暗黑模式切换" 功能。需求很简单:点击按钮,整个应用从亮色主题切换到暗色主题。

可他很快发现,这个功能藏着 "千层套路"。应用的组件层级深得像个迷宫:App -> Page -> Header -> Nav -> Button,每个组件都需要知道当前主题。

"总不能每层都传 props 吧?" 小李看着代码里层层嵌套的theme={theme},头都大了。光是给 5 层组件传参,就写了 20 多行重复代码,改一个地方要动一串组件,简直是 "牵一发而动全身"😫。

更糟的是,测试时发现某个深层组件漏传了 props,导致主题切换时出现 "一半亮一半暗" 的诡异画面。小李欲哭无泪:"这代码再写下去,我要先黑化了!"

第四章:useContext 的 "全局魔法"✨

"试试 Context 吧," 王哥又出现了,像个及时雨,"它能让状态像 Wi-Fi 一样,全局共享,不用一层层传线。"

王哥带着小李一步步操作:

第一步:创建 "信号塔"(上下文对象)

// ThemeContext.js
import { createContext } from 'react';
// 建立一个全局通信频道,默认值是light
export const ThemeContext = createContext("light");

第二步:搭建 "信号覆盖区"(Provider)

// App.jsx
import { useState } from 'react';
import { ThemeContext } from './ThemeContext';

function App() {
  const [theme, setTheme] = useState('light');
  return (
    {/* 用Provider包裹所有组件,相当于覆盖全局信号 */}
    <ThemeContext.Provider value={theme}>
      <Page /> {/* 所有子组件都能收到theme信号 */}
      <button onClick={() => {
        setTheme(theme === 'light' ? 'dark' : 'light');
      }}>切换主题</button>
    </ThemeContext.Provider>
  );
}

第三步:接收 "信号"(useContext)
王哥还教小李封装了个自定义 Hook,让获取主题更方便:

// useTheme.js
import { useContext } from 'react';
import { ThemeContext } from '../ThemeContext';

// 谁需要主题,调用这个Hook就行
export function useTheme() {
  return useContext(ThemeContext);
}

这下,不管多深的组件,只要一句const theme = useTheme(),就能拿到最新主题!点击切换按钮,整个应用瞬间统一变亮或变暗,没有一丝卡顿🎉。

终章:从 "bug 猎人" 到 "套路大师"🎯

小李看着整洁的代码,终于明白了:React Hooks 不是冷冰冰的 API,而是解决实际问题的 "套路"——

  • useState像个 "智能管家",帮你管理状态,还懂得合并更新来提高效率(记住用函数式更新处理依赖上一状态的场景哦~);
  • useContext像个 "全局广播",让深层组件通信不再需要 "层层传话",特别适合主题、用户信息这种全局状态。
Hook核心作用最佳场景关键注意点
useState管理组件内部状态单个组件的状态(如计数器、表单输入)依赖上一状态更新时,务必用函数式更新
useContext跨组件共享状态全局状态(如主题、用户信息、权限)避免过度使用(局部状态优先用 props)

从此,小李再也不怕状态管理和组件通信的难题了。他甚至开始期待更复杂的需求,因为他知道:掌握了这些 "套路",再棘手的问题都能迎刃而解😎。