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

调用Apollo refetch()后组件props.data未重新加载的问题排查

解决Apollo Recompose模式下Refetch不更新组件的问题

看起来你在使用Apollo的Recompose模式处理错误和加载状态时,遇到了refetch后组件状态不更新的问题——ErrorScreen一直显示,LoadingScreen没出来,数据也没更新。我之前也踩过类似的坑,核心是几个关键点没处理到位,咱们一步步来解决:

问题根源

  1. Apollo没有通知组件状态变化:默认情况下,graphql高阶组件不会在networkStatus变化时触发重渲染,而refetch时的加载状态是通过networkStatus(值为4,表示重新获取中)来体现的,不是loading(loading只对应首次查询)。
  2. 高阶组件没处理重新加载状态:你的renderWhileLoading和renderIfError只判断了初始的loading和error,没考虑refetch过程中的networkStatus变化。
  3. 手动处理refetch结果画蛇添足:你在handleRetry里手动then/catch了refetch的结果,但Apollo本来就会自动更新组件的data props,手动处理反而没意义,还可能掩盖了正常的更新流程。

具体修复步骤

1. 开启Apollo的网络状态通知

在你的withData配置里加上notifyOnNetworkStatusChange: true,这样组件会在networkStatus变化时重新渲染:

const options = { 
  fetchPolicy: 'cache-and-network',
  notifyOnNetworkStatusChange: true // 关键:开启状态变化通知
};
const withData = graphql(userEvents, options);

2. 调整高阶组件,处理networkStatus

修改renderWhileLoading

让它同时识别首次加载的loading和refetch中的networkStatus === 4(Apollo定义的重新获取状态对应值为4):

// 更新renderWhileLoading的判断逻辑
export const renderWhileLoading = (LoadingComponent) => 
  compose(
    branch(
      ({ data: { loading, networkStatus } }) => loading || networkStatus === 4,
      renderComponent(LoadingComponent)
    )
  );

修改renderIfError

确保只有在存在错误且不在重新加载状态时,才显示ErrorScreen:

// 更新renderIfError的判断逻辑
export const renderIfError = (ErrorComponent) => 
  compose(
    branch(
      ({ data: { error, networkStatus } }) => error && networkStatus !== 4,
      renderComponent(ErrorComponent)
    )
  );

3. 简化ErrorScreen的refetch调用

删掉handleRetry里的.then和.catch,只需要调用refetch()就行——Apollo会自动处理数据更新和状态变化:

const ErrorScreen = ({ refetch, data }) => {
  const handleRetry = () => {
    refetch(); // 直接调用,不用手动处理结果
  };
  return (
    <View style={styles.container}>
      <Text>{(data?.error?.message) || 'Something went wrong'}</Text>
      <Button title="Retry" onPress={handleRetry} />
    </View>
  );
};

4. 确认setRefetchProp正确传递refetch

确保setRefetchProp把data.refetch传递给了子组件,比如:

export const setRefetchProp = () => 
  withProps(({ data }) => ({
    refetch: data.refetch
  }));

修复后的流程

现在当你点击Retry按钮后:

  1. refetch()触发,Apollo把networkStatus设为4,组件重新渲染
  2. renderWhileLoading检测到networkStatus === 4,显示LoadingScreen,ErrorScreen隐藏
  3. 如果refetch成功:data更新,error消失,networkStatus回到正常状态,组件渲染原EventList
  4. 如果refetch失败:error保留,networkStatus回到非4状态,ErrorScreen重新显示

这样就完全符合你的预期结果了!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:17:08