React内置Hooks

以下是 React 中所有内置 Hooks 的完整分类解析,包含它们的核心作用和典型使用场景:

基础Hooks

useState

  • 作用: 管理组件内部状态
  • 使用:
jsx 复制代码
const [count, setCount] = useState(0);

// 惰性初始化: 仅在组件第一次渲染时调用,一般用于当初始化状态是一个昂贵的操作时,或者希望仅在状态第一次使用时才计算其值

// 计算昂贵
const [theme, setTheme] = useState(() => {
   // 计算昂贵的过程
});

// 第一次渲染时使用
const [theme, setTheme] = useState(() => {
    const localTheme = localStorage.getItem('theme');
    return localTheme ? localTheme : 'light';
});

useEffect

  • 作用: 处理副作用操作
  • 使用:
jsx 复制代码
useEffect(() => {
    /* 会在组件挂载时或依赖项更新时触发 */
    
    /* 执行相关得副作用 */

    // 返回得函数
    return () => {
        /* 会在组件卸载时调用 */
    };
}, [deps]);
  • 执行时机

会在DOM更新之后,浏览器绘制之后异步执行,不会阻塞页面得绘制,但如果在此Hook中进行了一些操作DOM的副作用处理,可能会导致页面出现闪烁的现象,如果需要解决这种现象,可以使用useLayoutEffectHook函数,它在DOM更新之后,与浏览器页面绘制同步执行。

useContext

  • 作用: 访问Context值
  • 使用
jsx 复制代码
// 创建context

const myContext = React.createContext(initValue);

// 父组件
<myContextProvider value={{
    name: '张三',
    age: 18
}}>
    ...
    <Child />
</myContextProvider>

// 子组件
const contextData = useContext(myContext); // {  name: '张三', age: 18 }

高级状态管理

useReducer

  • 作用: 复杂状态逻辑管理(类似Redux状态管理)
  • 使用
jsx 复制代码
const myReducer = (currState, action) => {
    const { type, payload } = action;
    switch(type) {
        case: 'loading':
            return { ...currState, loading: true };
        case 'success':
            return { ...currState, loading: false, data: payload };
        case 'error':
            return { ...state, loading: false, error: payload };
        default:
            return currState;
    }
};

function Demo() {
    const [state, dispatch] = useReducer({
        isLoading: false, 
        data: null, 
        error: null,
    });
    
    const fetchData = () => {
        dispatch({ type: 'loading' });
        try {
            const res = await fetch('https://api.example.com/data');
            const data = await res.json();
            dispatch({ type: ''success', payload: data });
        } catch (err) {
            dispatch({ type: 'error', payload: error });
        }
    };
    
    useEffect(() => {
        fetchData();
    }, []);
    
    return <div>...</div>
}

性能优化

useMemo

  • 作用: 缓存计算结果(类似于Vue中的计算属性)
  • 使用
jsx 复制代码
// 对于计算过程比较复杂的值,我们可以将它进行缓存,每当组件重新渲染时,只有当依赖项变化时,我们才去重新计算,否则使用缓存的值。

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

useCallback

  • 作用: 缓存回调函数引用
  • 使用
jsx 复制代码
// 因组件每次重新渲染时,其组件内部的函数都会重新创建,这样就会造成接收该函数的子组件进行不必要的更新,影响性能。useCallback可以保存函数的引用,只有当其依赖项发生变化时,我们才重新创建函数。

const Child = ({ onClick }) => {
  console.log('update');
  return <button onClick={onClick}>Click me</button>;
};

const ChildMemo = React.memo(Child);

export default function Test() {
  const [count, setCount] = useState(0);

  const handleClick = useCallback(() => {
    console.log(count);
  }, [count]);

  return (
    <div>
      <ChildMemo onClick={handleClick} />
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

DOM/Ref操作

useRef

  • 作用: 获取DOM引用/保存可变值
  • 使用
jsx 复制代码
const inputRef = useRef(null);
<input ref={inputRef} />

// 保存任意可变值(不会触发重新渲染)
const intervalId = useRef();

useImperativeHandle

  • 作用: 自定义暴露给父组件的实例值
  • 使用
jsx 复制代码
import React, { useRef, useImperativeHandle, forwardRef } from 'react';

const TextInput = forwardRef((props, ref) => {
  const inputRef = useRef();

  // 使用 useImperativeHandle 暴露 focus 方法
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    }
  }));

  return <input ref={inputRef} />;
});

function ParentComponent() {
  const textInputRef = useRef();

  const handleFocus = () => {
    // 通过 ref 调用子组件暴露的 focus 方法
    textInputRef.current.focus();
  };

  return (
    <div>
      <TextInput ref={textInputRef} />
      <button onClick={handleFocus}>Focus the input</button>
    </div>
  );
}

export default ParentComponent;

特殊场景Hooks

useLayoutEffect

  • 作用: 同步DOM操作的副作用
  • 使用
jsx 复制代码
// 一般在DOM更新完成之后浏览器渲染之前进行一些DOM操作,避免页面出现闪速问题

useLayoutEffect(() => {
    /* DOM操作 */
}, []);

React18新增Hooks

useId

  • 作用: 生成唯一ID
  • 使用
jsx 复制代码
const id = useId();

useDeferredValue

  • 作用: 延迟更新某个值
  • 使用
jsx 复制代码
// 适用于输入防抖等场景(列表搜索)

import React, { useState, useDeferredValue, useMemo } from 'react';

const LargeList = () => {
  const [query, setQuery] = useState('');
  const deferredQuery = useDeferredValue(query);  // 延迟查询
  const data = useMemo(() => {
    // 生成一个大量的数据列表
    return Array.from({ length: 10000 }, (_, index) => `Item ${index + 1}`);
  }, []);

  const filteredData = useMemo(() => {
    // 基于延迟的查询词来过滤数据
    return data.filter(item => item.toLowerCase().includes(deferredQuery.toLowerCase()));
  }, [deferredQuery, data]);

  return (
    <div>
      <input
        type="text"
        value={query}
        onChange={(e) => setQuery(e.target.value)}
        placeholder="Search in list"
      />
      <ul>
        {filteredData.map(item => (
          <li key={item}>{item}</li>
        ))}
      </ul>
    </div>
  );
};

export default LargeList;
相关推荐
weixin_3823952313 分钟前
为小工厂量身打造:本地部署的物料管理系统带缺料计算
前端·制造
__zRainy__19 分钟前
解决pnpm v10+不自动构建
前端·pnpm·工程化
猫猫不是喵喵.1 小时前
Vue3 Props 属性
前端·javascript·vue.js
醉城夜风~2 小时前
CSS元素显示模式(display)
前端·css
AI大模型-小华3 小时前
Codex 三方充值快速入门指南
java·前端·数据库·chatgpt·ai编程·codex·chatgpt pro
做前端的娜娜子5 小时前
同一链接实现 PC Web 与移动 H5 自适应
前端·掘金·金石计划
小帅不太帅5 小时前
架构没变、规模没变,DeepSeek V4 Flash 正式版凭什么暴涨 47 分?
前端·aigc·deepseek
jarvisuni5 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法
卷福同学7 小时前
AI编程出海第二步:验证关键词能否做站
前端·人工智能·后端