我的场景是这样的:
我先把 API a 和 b 用 react query 抽象成 hook:
const useFetchA = (params) => { return useQuery(['fetchA', params], async () => { return await API.a(params) }) } // useFetchB 也类似,就不写了
然后在很多组件上都有这样的两行:
const resA = useFetchA('xxx'); const resB = useFetchB('yyy');
我也想过要 API.a 和 API.b 放在一个 hook 里,但是这样,单独使用 API.a 或 API.b 的时候就不方便了。
也想过把 useFetchA 和 useFetchB 再放在一个 hook 里,类似这样:
const useFetchAandB = (params) => { const {data: resA} = useFetchA(params) const {data: resB} = useFetchB(resA) }
不知道这样是否可行?有什么隐患?是否符合规范?
![]() | 1 codehz 2022-09-15 23:41:25 +08:00 react query 不是自带缓存管理的吗( 重复写又不会重复请求 |
![]() | 2 tonytonychopper 2022-09-15 23:56:19 +08:00 我理解 hook 就是可以随便组合的,只要逻辑清晰就行了 |
![]() | 3 RRRSSS OP |
![]() | 4 codehz 2022-09-16 00:12:04 +08:00 @RRRSSS 这就是为啥不应该用 useEffect 来做这种操作( https://blog.skk.moe/post/why-you-should-not-fetch-data-directly-in-use-effect/ |
![]() | 5 changwei 2022-09-16 00:32:41 +08:00 via Android 用 swr ,把前一个 swr 请求的返回结果作为下一个 swr 的 key 即可,不用担心缓存问题,swr 会自动帮你解决 |
![]() | 6 RRRSSS OP @changwei emm.. 我换个例子吧,不是请求,只是一个副作用,比如第一个 hook 是改 title ,第二个 hook 是根据这个 title 是否是 'homepage' 而去 useWindowSize 。好吧,我没编出来。就是这个意思,怎么弄呢、 |
![]() | 7 RRRSSS OP @codehz @tonytonychopper 关键是如果想要这种就不行了,不能放在 if 里: ```js const useFetchAandB = (params) => { const {data: resA} = useFetchA(params) if (resA === 'foo') { const {data: resB} = useFetchB(resA) } } ``` 这样就不能抽象成 hook 了吧 |
![]() | 8 Pastsong 2022-09-16 00:51:31 +08:00 useFetchAandB useFetchA useFetchB 同时存在,想用啥用啥 |
10 CptDoraemon 2022-09-16 02:18:30 +08:00 @RRRSSS ```js const useFetchAandB = (params) => { const {data: resA} = useFetchA(params); const {data: resB, doFetchB} = useFetchB(); const previousResARef = useRef(resA); useEffect(() => { if (previousResARef.current !== 'foo' && resA === 'foo') { } }) ``` |
11 CptDoraemon 2022-09-16 02:20:00 +08:00 tab 到回复了 lol ```js const useFetchAandB = (params) => { const {data: resA} = useFetchA(params); const {data: resB, doFetchB} = useFetchB(); const previousResARef = useRef(resA); useEffect(() => { if (previousResARef.current !== 'foo' && resA === 'foo') { doFetchB(resA) } }) ``` |
![]() | 12 codehz 2022-09-16 10:29:32 +08:00 ![]() (再动态一点可以考虑包一层组件,虽然 hook 不能写条件,但是组件可以随便加 做类似无限滚动的话还可以用 useSWRInfinite |
13 jjwjiang 2022-09-16 11:17:11 +08:00 B 既然依赖 A 的结果,那你定义 useFetchB 的时候给个入参就行了,这样所有用到 fetchB 的地方就必须传入 A 的结果 如果 A 的查询和每个页面内容无关,那直接把 A 写到 useFetchB 里面去 |
![]() | 14 tonytonychopper 2022-09-17 00:36:31 +08:00 @RRRSSS #7 这样写本来就会有坑,如果一定要这么写的话,不如在 useFetchB 内部做判断: function useFetchB if resA === 'foo' then do something |