如何让React自定义Hook仅在Apollo加载完成且数据可用时执行?
问题解答
1. 你的自定义Hook实现存在问题
当前代码里的useEffect依赖数组只添加了id,但新增的loading参数未被纳入依赖,同时你用到的type也缺失在依赖数组中,这会导致两个问题:
- 初始阶段
loading为true,effect不执行,window.mydata不会被赋值 - 当
loading变为false时,如果id没有变化,这个effect不会重新触发,window.mydata依然无法被正确设置
正确的修改方式是把loading和type都加入依赖数组,调整后的代码如下:
useEffect(() => { if (!loading) { window.mydata = { id: `${id}`, type: `${type}` }; } }, [id, type, loading]); // 补充所有用到的依赖项
另外,如果你希望脚本也只在数据加载完成后再引入,需要注意useScript作为自定义Hook不能放在useEffect内部,可在Hook开头添加条件判断:
const useMyHook = ({ id, type, loading }: Props) => { // 仅在数据加载完成后加载脚本 if (!loading) { useScript('https:domain/main.js'); useScript('https://domain/main2.js'); } useEffect(() => { if (!loading) { window.mydata = { id: `${id}`, type: `${type}` }; } }, [id, type, loading]); };
2. 片段查询先返回undefined的原因
这和Fragments无关,是Apollo Client useQuery的固有执行逻辑:
- 组件首次渲染时,GraphQL请求还在处理中,Apollo还未拿到后端返回的数据,此时
useQuery返回的data就是undefined,loading状态为true - 当请求成功完成、数据返回后,
useQuery会更新状态,loading变为false,data被填充为查询结果,组件触发重新渲染,此时就能拿到有效数据
你之前在组件return里用!loading && foo控制的是UI渲染,但自定义Hook的执行不受return逻辑限制——组件挂载时Hook就会运行,不管return里的条件,所以即使UI不渲染,Hook里的初始逻辑依然会执行,导致window.mydata可能被提前设置为对应undefined的id值。
内容的提问来源于stack exchange,提问作者meez
相关产品推荐
相关产品推荐

