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;
相关推荐
zimoyin8 分钟前
Kotlin 协程实战:实现异步值加载委托,对值进行异步懒初始化
java·前端·kotlin
赵大仁40 分钟前
React Native 与 Expo
javascript·react native·react.js
程序员与背包客_CoderZ2 小时前
Node.js异步编程——Callback回调函数实现
前端·javascript·node.js·web
非凡ghost2 小时前
Pale Moon:速度优化的Firefox定制浏览器
前端·firefox
清灵xmf2 小时前
从 Set、Map 到 WeakSet、WeakMap 的进阶之旅
前端·javascript·set·map·weakset·weakmap
11054654013 小时前
11、参数化三维产品设计组件 - /设计与仿真组件/parametric-3d-product-design
前端·3d
爱笑的林羽3 小时前
Mac M系列 安装 jadx-gui
前端·macos
运维@小兵3 小时前
vue使用路由技术实现登录成功后跳转到首页
前端·javascript·vue.js
肠胃炎3 小时前
React构建组件
前端·javascript·react.js
邝邝邝邝丹3 小时前
React学习———React.memo、useMemo和useCallback
javascript·学习·react.js