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

import { useWallet } from "util/hooks";

const Points = () => {

  const { id, info} = useWallet();

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

}

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

阅读 1.7k
5 个回答

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]);
}

如果id和info 请求到的值 跟初始化的值 不可能一样 你就正常判断 类似if&&info 的时候请求
如果id和info 请求到的值 跟初始化的值有可能一样 那你就重新设个变量为0 id和info 请求成功 让变量+1 然后useEffect判断变量===2的时候 fetchData() 就只执行一次了

推荐问题