apollo-client中onError、onCompleted回调相比自带返回变量有何适用场景?
onCompleted和onError既不是冗余设计,也不存在天生的性能问题。你之前的写法性能差是因为额外加了不必要的setState操作,和回调本身无关。确实在大部分需要渲染请求结果/错误的场景下,直接使用useQuery/useLazyQuery返回的data、error是更简洁高效的选择,但仍然有不少场景使用回调会更合适:
- 一次性副作用执行场景:如果请求完成/出错后需要执行和渲染无关的一次性操作,比如弹出操作成功/失败的提示、上报错误日志、页面跳转、写入本地存储等,用回调会比监听
data/error的useEffect更可靠。因为data/error会一直存在于返回结果中,如果你不在useEffect里加额外的执行标记,组件重渲染时很容易重复触发副作用;而回调只会在请求结束的那一刻触发一次,不需要额外写清理逻辑。 - 非响应式的数据处理场景:如果你拿到请求结果后不需要用来驱动组件渲染,只是需要给第三方非React库传入数据(比如给ECharts实例更新配置、给原生DOM操作传值),直接在回调里处理数据即可,不需要把数据存到状态里,反而能减少不必要的组件重渲染。
- 多请求联动的逻辑聚合场景:如果需要在A请求完成后用返回结果触发B请求,把B请求的调用写在A的
onCompleted里,逻辑会比在外层写多个useEffect监听不同请求的data更集中,也更容易避免依赖项遗漏导致的bug。 - 请求结果的过滤/限流场景:如果你只需要处理特定条件下的请求结果(比如连续触发多次同个查询时,只处理最后一次的返回结果),在回调里做判断会比在外层监听
data更方便,不需要额外维护请求ID之类的标记变量。
回调本身的性能开销极低,你之前的写法之所以会多出重渲染,是因为在回调里手动调用了setState,相当于Apollo更新请求结果触发一次重渲染后,你的setState又触发了第二次重渲染,这是不合理的用法导致的,不是回调本身的问题。如果回调里没有触发组件更新的操作,完全不会带来额外的性能损耗。
内容的提问来源于stack exchange,提问作者PubSub
相关产品推荐
相关产品推荐

