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

如何确保Ionic7+React18中无依赖useEffect仅执行一次?

React 18 + Ionic 7 中 useEffect 执行两次的问题解决

问题场景

我正在开发基于Ionic 7、React 18的应用,给useEffect传递了空依赖数组,本以为能确保副作用只执行一次,但实际UserService.getProfile()被调用了两次。

App.tsx 代码

setupIonicReact();

const App: React.FC = () => {

  useEffect(() => {
    console.log("Loading user profile info in app..." + new Date().getUTCMilliseconds());
    UserService.getProfile()
      .then((user) => {
        console.log("User: " + JSON.stringify(user));
      })
      .catch((error) => {
        console.error("Error fetching profile:", error);
      });
  }, []);
  

  return (
    <IonApp>
      <IonReactRouter>
        <IonHeader>
          <IonToolbar>
            <IonButtons slot="start">
              <IonButton>
                <IonIcon icon={logoReact} />
              </IonButton>
            </IonButtons>
            <IonTitle>LOL Greetings</IonTitle>
            <IonButtons slot="end">
              <IonButton>
                <IonIcon icon={search} />
              </IonButton>
              <IonButton>
                <IonIcon icon={personCircle} />
              </IonButton>
            </IonButtons>
          </IonToolbar>
          <IonToolbar>
            <CategorySelectComponent />
          </IonToolbar>
        </IonHeader>

        <IonContent className="ion-padding" scroll-y>
        Test
        </IonContent>
      </IonReactRouter>
    </IonApp>
  );
};

export default App;

main.tsx 代码

const container = document.getElementById("root");
const root = createRoot(container!);
root.render(
  <React.StrictMode>
      <App />
  </React.StrictMode>
);

原因与解决方法

原因

这是React 18严格模式(<React.StrictMode>)的开发环境特性:为了帮开发者提前发现重复执行副作用可能引发的bug,StrictMode会在开发环境中刻意重复执行useEffect等副作用逻辑,但生产环境不会有这个行为。你的代码正好用StrictMode包裹了App,所以出现了两次执行的情况。

解决方案

方案1:移除StrictMode(开发环境临时验证用)

直接修改main.tsx,去掉<React.StrictMode>包裹,开发环境下useEffect就只会执行一次:

const container = document.getElementById("root");
const root = createRoot(container!);
root.render(
    <App />
);

注意:StrictMode能有效检测潜在问题,不建议在生产环境移除,仅作为开发时临时验证手段。

方案2:用Ref标记执行状态(推荐长期使用)

如果想保留StrictMode的优势,同时确保API只调用一次,可以用useRef记录副作用是否已执行:

setupIonicReact();

const App: React.FC = () => {
  const hasFetched = useRef(false);

  useEffect(() => {
    if (!hasFetched.current) {
      console.log("Loading user profile info in app..." + new Date().getUTCMilliseconds());
      UserService.getProfile()
        .then((user) => {
          console.log("User: " + JSON.stringify(user));
        })
        .catch((error) => {
          console.error("Error fetching profile:", error);
        });
      hasFetched.current = true;
    }
  }, []);
  
  // 其余返回代码不变...
};

export default App;

这种方式既保留了StrictMode的检测能力,又能避免重复调用API,适合长期使用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 21:23:23