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;
相关推荐
初遇你时动了情37 分钟前
JS中defineProperty/Proxy 数据劫持 vue3/vue2双向绑定实现原理,react 实现原理
javascript·vue.js·react.js
阿华的代码王国1 小时前
【Android】RecyclerView实现新闻列表布局(1)适配器使用相关问题
android·xml·java·前端·后端
汪子熙1 小时前
Angular 最新的 Signals 特性详解
前端·javascript
Spider_Man1 小时前
前端路由双雄传:Hash vs. History
前端·javascript·html
南方kenny1 小时前
CSS Grid 布局:从入门到精通,打造完美二维布局
前端·javascript·css
小泡芙丫1 小时前
从买房到代码:发布订阅模式的"房产中介"之旅
前端·javascript
企鹅吧1 小时前
前端导出 pdf 与 跑马灯效果 最佳实践
前端·javascript·vue.js
南方kenny1 小时前
移动端适配的利器:lib-flexible 原理与实战
前端·javascript·react.js
沫小北1 小时前
HarmonyOS 自定义日期选择器组件详解
前端
大土豆的bug记录2 小时前
鸿蒙拉起系统定位和app授权定位
前端·javascript·harmonyos