You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建自定义React Hook避免useEffect初始渲染时执行?

实现跳过初始渲染的自定义useEffect Hook

你可以通过创建一个基于useRef的自定义Hook,来标记是否为组件的初始渲染,从而实现仅在依赖项变化时执行副作用逻辑,跳过首次渲染的触发。

自定义Hook实现

import { useState, useEffect, useRef } from 'react';

// 自定义Hook:仅在依赖项更新时执行副作用,跳过初始渲染
export function useEffectUpdate(callback, dependencies) {
  const isFirstRender = useRef(true);

  useEffect(() => {
    // 首次渲染时仅标记状态,不执行回调
    if (isFirstRender.current) {
      isFirstRender.current = false;
      return;
    }
    // 非首次渲染,执行传入的回调,并保留清理函数的返回
    return callback();
  }, dependencies);
}

改造你的Counter组件

将原来的useEffect替换为这个自定义Hook,就能解决localStorage被初始值覆盖的问题:

import React, { useState, useEffect } from 'react';
import { useEffectUpdate } from './useEffectUpdate';

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

  // 仅在count变化时保存到localStorage,跳过初始渲染
  useEffectUpdate(() => {
    localStorage.setItem('count', count.toString());
  }, [count]);

  useEffect(() => {
    // 加载已保存的count(初始渲染时执行一次)
    const savedCount = localStorage.getItem('count');
    if (savedCount) {
      setCount(parseInt(savedCount, 10));
    }
  }, []);

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

逻辑说明

  1. 初始渲染标记:用useRef存储isFirstRender状态,它的更新不会触发组件重渲染,比useState更高效。
  2. 跳过首次执行:首次渲染时,仅将isFirstRender设为false,不执行副作用回调。
  3. 依赖变化触发:当依赖项(比如count)更新时,isFirstRender已经是false,此时执行传入的副作用逻辑。
  4. 支持清理函数:自定义Hook会返回callback的返回值,所以如果你的副作用需要清理(比如取消订阅、定时器),可以正常返回清理函数,和原生useEffect的行为一致。

内容的提问来源于stack exchange,提问作者user25148175

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 12:13:17