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

startTransition无法阻止React Native中Suspense触发加载状态

React Native中Suspense配合startTransition阻止fallback失效的解决方案

问题重现

使用Expo v49.0.0构建React Native v0.72.4应用时,在useSuspenseQuery的fetchMore调用外层包裹startTransition,原本预期能阻止组件触发Suspense的fallback加载状态(Web环境下正常生效),但在React Native中无论是否使用transition,执行loadMore时组件都会回到加载状态。

相关代码片段:

function Container({
  navigation,
}: ContainerProps): JSX.Element {
  const { ctx } = useTopTabContext();
  const { address } = ctx;
  const [page, setPage] = useState(1);
  const { client, data, fetchMore } = useSuspenseQuery(
    QUERY,
    {
      fetchPolicy: "cache-and-network",
      variables: {
        address,
        filters: {
          limit: 100,
        },
      },
    }
  );

  const loadMore = () => {
    if (data?.wallet?.items?.pageInfo.hasNextPage) {
      const nextPage = page + 1;
      startTransition(() => {
        fetchMore({
          variables: {
            filters: {
              limit: 100,
              page: nextPage,
            },
          },
        }).then(() => {
          setPage(nextPage);
        });
      });
    }
  };

  // ...其余代码
}

可能的解决方案

1. 切换到useQuery而非useSuspenseQuery

useSuspenseQuery的设计逻辑是只要查询处于pending状态就会触发Suspense,即使在transition中。换成普通的useQuery,手动管理加载状态,这样可以完全控制何时显示加载UI,避免Suspense自动触发fallback:

const { data, fetchMore, isFetching } = useQuery(QUERY, {
  fetchPolicy: "cache-and-network",
  variables: {
    address,
    filters: { limit: 100 },
  },
});

const loadMore = () => {
  if (data?.wallet?.items?.pageInfo.hasNextPage) {
    const nextPage = page + 1;
    startTransition(() => {
      fetchMore({
        variables: {
          filters: { limit: 100, page: nextPage },
        },
      }).then(() => setPage(nextPage));
    });
  }
};

之后在渲染时,仅在初始加载阶段显示全局fallback,加载更多时用列表底部的局部加载提示替代,不再依赖Suspense的自动触发逻辑。

2. 调整Apollo Client的fetchPolicy

尝试将fetchPolicy改为"cache-first"或"network-only"(根据业务需求选择):

  • cache-first会优先使用缓存数据,只有缓存不存在时才发起网络请求,能避免加载更多时因网络请求触发Suspense;
  • network-only强制走网络,但可以配合手动状态管理控制加载UI的显示时机。

3. 绕过Suspense,手动管理加载状态

在组件内新增加载状态变量,完全接管加载逻辑,不让Suspense干预加载更多的过程:

const [isLoadingMore, setIsLoadingMore] = useState(false);

const loadMore = () => {
  if (data?.wallet?.items?.pageInfo.hasNextPage && !isLoadingMore) {
    const nextPage = page + 1;
    startTransition(() => {
      setIsLoadingMore(true);
      fetchMore({
        variables: { filters: { limit: 100, page: nextPage } },
      }).then(() => {
        setPage(nextPage);
        setIsLoadingMore(false);
      });
    });
  }
};

然后在FlashList的尾部渲染isLoadingMore对应的加载组件即可。

4. 检查Apollo Client版本兼容性

确保@apollo/client版本与React Native、React版本匹配,比如v3.8+版本对React 18的Suspense支持更完善,若当前使用旧版本,升级到兼容的最新版本可能解决问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 15:00:59