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

Ionic-React中hideLoading()函数失效问题求助

Ionic React + Supabase 加载状态异常与useEffect重复触发问题

问题点

  • 调用fetchCategories时,hideLoading()失效,加载动画持续转动
  • 页面加载阶段useEffect钩子触发两次,仅第二次加载状态表现正常
  • 核心需求:实现菜单点击逻辑,通过更新father变量获取对应子分类数据

原代码

const fetchMenu = async () => {
    try {
      const { data: menuData, error } = await supabase.from('categoria').select('*').eq('pai', 0);
      if (error) throw error;
      setMenu(menuData);
      console.log(menuData);
    } catch (error: any) {
      await showToast({ message: error.message || error.error_description, duration: 5000 });
    }
  }

const fetchCategories = async (father: number) => {
    showLoading();
    try {
      const { data: categoriesData, error } = await supabase.from('categoria').select('*').eq('pai', father);
      if (error) throw error;
      setCategories(categoriesData);
      console.log(categoriesData);
    } catch (error: any) {
      await showToast({ message: error.message || error.error_description, duration: 5000 });
    }
    hideLoading();
  }

useEffect(() => {
    fetchMenu();
  }, []);

  useEffect(() => {
    if (father != null){
      fetchCategories(father);
    }
  }, [father]);

return (
    <IonPage>
      {/*CABEÇALHO*/}
      <IonHeader>
        <IonToolbar>
          <IonTitle>Fossil Fashion</IonTitle>
        </IonToolbar>
        <IonSegment>
          {menu?.map((menuPage: any) => (
            <IonSegmentButton key={menuPage.id} value={Number(menuPage.id)} onClick={(e) => setFather(Number(e.currentTarget.value))}>
              <IonLabel>{menuPage.nome}</IonLabel>
            </IonSegmentButton>
          ))}
        </IonSegment>
      </IonHeader>

      {/*CORPO*/}
      <IonContent>
        <IonSearchbar placeholder="Pesquisa"></IonSearchbar>
        <IonGrid>
          {categories?.map((category: any) => (
            <IonRow key={category.id}>
              <IonItemGroup>
                <IonItemDivider>
                  <IonLabel>{category.nome}</IonLabel>
                </IonItemDivider>
              </IonItemGroup>
            </IonRow>
          ))}
        </IonGrid>
    </IonPage>
);

解决方案

1. 修复加载状态失效问题

问题根源在于hideLoading()未被可靠执行,且Ionic的Loading控制器需要通过实例调用dismiss()确保正确关闭。修改fetchCategories:

const fetchCategories = async (father: number) => {
  // 获取Loading实例,确保每次请求对应唯一实例
  const loadingInstance = await showLoading();
  try {
    const { data: categoriesData, error } = await supabase.from('categoria').select('*').eq('pai', father);
    if (error) throw error;
    setCategories(categoriesData);
  } catch (error: any) {
    await showToast({ message: error.message || error.error_description, duration: 5000 });
  } finally {
    // 无论请求成功/失败,都关闭加载动画
    await loadingInstance.dismiss();
  }
}

若你的showLoading()是全局封装方法,需确保它返回Ionic Loading实例,而非仅触发显示。

2. 处理useEffect重复触发

React 18+开发模式下,StrictMode会强制useEffect执行两次,这是开发环境的校验机制,生产环境会自动消失。若需避免重复请求,可添加状态锁:

const [hasFetchedMenu, setHasFetchedMenu] = useState(false);

useEffect(() => {
  if (!hasFetchedMenu) {
    fetchMenu();
    setHasFetchedMenu(true);
  }
}, [hasFetchedMenu]);

3. 优化菜单点击逻辑

简化onClick事件,直接使用菜单ID,避免类型转换与DOM取值:

<IonSegmentButton 
  key={menuPage.id} 
  value={menuPage.id} 
  onClick={() => setFather(menuPage.id)}
>
  <IonLabel>{menuPage.nome}</IonLabel>
</IonSegmentButton>

4. 可选:为菜单加载添加状态控制

若菜单加载也需要显示动画,对fetchMenu做同样改造:

const fetchMenu = async () => {
  const loadingInstance = await showLoading();
  try {
    const { data: menuData, error } = await supabase.from('categoria').select('*').eq('pai', 0);
    if (error) throw error;
    setMenu(menuData);
  } catch (error: any) {
    await showToast({ message: error.message || error.error_description, duration: 5000 });
  } finally {
    await loadingInstance.dismiss();
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 23:00:55