useEffect依赖多个项,在组件初始化时怎么保证useEffect只执行一次?

import { useWallet } from "util/hooks";

const Points = () => {

  const { id, info} = useWallet();

  useEffect(() => {
    fetchData();
  }, [id, info]);

}

像上面的场景,useEffect依赖多个项,而且组件初始化的时候会同时获取id和info两个值,导致useEffect会执行两次,怎么才能保证组件初始化时useEffect只执行一次呢?

阅读 1.3k
4 个回答

useEffect 钩子在某些情况下会执行多次的现象主要出现在 React 18 及其之后的版本中。这是因为 React 18 引入了严格模式(Strict Mode),在开发环境中会故意调用某些生命周期方法和钩子两次,以帮助开发者发现潜在的问题。

import { useWallet } from "util/hooks";
import { useEffect, useRef } from "react";

const Points = () => {
  const { id, info } = useWallet();
  const hasInitialized = useRef(false);

  // 只在组件首次渲染时执行的初始化请求
  useEffect(() => {
    if (!hasInitialized.current) {
      hasInitialized.current = true;
      fetchData();
    }
  }, []); // 空依赖数组,只执行一次

  // 处理 id 或 info 更新的情况
  useEffect(() => {
    if (hasInitialized.current && id && info) {
      fetchData();
    }
  }, [id, info]);

  return (
    // Your component JSX here
  );
}

判断一下

useEffect(() => {
  if (id && info) {
    fetchData();
  }
}, [id, info]);

这样呢?

import { useWallet } from "util/hooks";
import { useEffect, useRef } from "react";

const Points = () => {
  const { id, info } = useWallet();
  const hasInitialized = useRef(false);

  useEffect(() => {
    // 初次初始化执行
    if (!hasInitialized.current) {
      hasInitialized.current = true;
      fetchData();
    } else {
      // 后续执行
      fetchData();
    }
  }, [id, info]);

  return (
    // Your component JSX here
  );
}

四种方法你都可以试一下

import { useWallet } from "util/hooks";

const Points = () => {
  const { id, info } = useWallet();
  const isInitialMount = useRef(true);

  useEffect(() => {
    if (isInitialMount.current) {
      isInitialMount.current = false;
      fetchData();
    } else {
      
      if (id && info) {
        fetchData();
      }
    }
  }, [id, info]);
}
import { useWallet } from "util/hooks";

const Points = () => {
  const { id, info } = useWallet();
  const deps = useMemo(() => ({ id, info }), [id, info]);

  useEffect(() => {
    if (deps.id && deps.info) {
      fetchData();
    }
  }, [deps]); // 只依赖一个对象
}
import { useWallet } from "util/hooks";

const Points = () => {
  const { id, info } = useWallet();
  
  const fetchDataCallback = useCallback(() => {
    if (id && info) {
      fetchData();
    }
  }, [id, info]);

  useEffect(() => {
    fetchDataCallback();
  }, []); 
}
import { useWallet } from "util/hooks";

const Points = () => {
  const { id, info } = useWallet();

  useEffect(() => {
    if (id && info) {
      fetchData();
    }
  }, [id, info]);
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题