如何避免Apollo Client的onError错误链路对同一错误重复触发两次?
问题原因
- 链路重复添加:你在
<App>组件内部执行client.setLink()的逻辑,在React 18的严格模式(<StrictMode>)下,组件会经历两次挂载执行,第一次执行后链路变为[errorLink实例1, 原始HttpLink],第二次执行时会在已经插入过errorLink的链路基础上,再插入第二个errorLink实例,最终链路变为[errorLink实例2, errorLink实例1, 原始HttpLink]。当网络错误触发时,两个errorLink都会执行回调,自然会弹出两次错误提示。 - 错误传递逻辑:默认情况下onError链接处理完错误后,会继续把错误向下传递给链路的后续节点,你没有主动终止错误传递,也会叠加重复触发的概率,该场景核心原因还是链路重复添加了errorLink。
解决方法
方案1:初始化ApolloClient时直接配置完整链路(最推荐)
不要动态修改client的链路,在创建实例的时候就把errorLink放到链路配置里,代码如下:
import { from, HttpLink } from '@apollo/client'; import { onError } from '@apollo/client/link/error'; // 先定义errorLink const errorLink = onError(({ graphQLErrors, networkError }) => { if (graphQLErrors) { message.error('GraphqlError'); } if (networkError) { message.error('NetworkError'); } // 如果需要终止错误继续传递,可以加下面这行 // return Observable.empty(); }); // 定义httpLink,原来的uri、credentials参数挪到这里配置 const httpLink = new HttpLink({ uri: configuration.API, credentials: 'include' }); const client = new ApolloClient({ cache: cacheInstance, // 这里直接传入组合好的链路 link: from([errorLink, httpLink]), typeDefs, });
这样链路从创建之初就是固定的,不会有重复添加的问题,也符合Apollo Client的最佳实践。
方案2:如果必须动态添加链路,避免重复执行
如果你的业务场景确实需要在组件挂载后才添加errorLink,那修改动态设置的逻辑,加判断防止重复插入:
// 在App组件内 useEffect(() => { // 加个自定义标记,防止重复添加errorLink if (!client.link?._hasErrorLink) { const errorLink = onError(({ graphQLErrors, networkError }) => { if (graphQLErrors) { message.error('GraphqlError'); } if (networkError) { message.error('NetworkError'); } }); const newLink = from([errorLink, client.link]); // 给新链路加自定义标记 newLink._hasErrorLink = true; client.setLink(newLink); } }, []);
如果不需要错误继续向下传递,可以在onError回调末尾返回Observable.empty(),主动终止链路的错误传递,也能避免后续其他链路节点触发重复的错误逻辑。
内容的提问来源于stack exchange,提问作者Robin
相关产品推荐
相关产品推荐

