V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
RRRSSS
V2EX  ›  React

简化 react hook 的方法?

  •  
  •   RRRSSS · 2022-09-15 23:37:02 +08:00 · 2297 次点击
    这是一个创建于 560 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我的场景是这样的:

    1. API a 是比较常见的接口,几乎每个页面都要调用
    2. API b 是依赖 a 的结果,去调用的

    我先把 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)
    }
    

    不知道这样是否可行?有什么隐患?是否符合规范?

    14 条回复    2022-09-17 00:36:31 +08:00
    codehz
        1
    codehz  
       2022-09-15 23:41:25 +08:00
    react query 不是自带缓存管理的吗(
    重复写又不会重复请求
    tonytonychopper
        2
    tonytonychopper  
       2022-09-15 23:56:19 +08:00
    我理解 hook 就是可以随便组合的,只要逻辑清晰就行了
    RRRSSS
        3
    RRRSSS  
    OP
       2022-09-16 00:09:58 +08:00
    @codehz 好吧,可能我例子特殊了,如果不用 react query 呢?只是 axios 请求呢?

    我只是想用这个例子,看看这种情况怎么样比较合适?
    codehz
        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/
    changwei
        5
    changwei  
       2022-09-16 00:32:41 +08:00 via Android
    用 swr ,把前一个 swr 请求的返回结果作为下一个 swr 的 key 即可,不用担心缓存问题,swr 会自动帮你解决
    RRRSSS
        6
    RRRSSS  
    OP
       2022-09-16 00:41:20 +08:00
    @changwei emm..

    我换个例子吧,不是请求,只是一个副作用,比如第一个 hook 是改 title ,第二个 hook 是根据这个 title 是否是 'homepage' 而去 useWindowSize 。好吧,我没编出来。就是这个意思,怎么弄呢、
    RRRSSS
        7
    RRRSSS  
    OP
       2022-09-16 00:43:21 +08:00
    @codehz @tonytonychopper 关键是如果想要这种就不行了,不能放在 if 里:

    ```js
    const useFetchAandB = (params) => {
    const {data: resA} = useFetchA(params)
    if (resA === 'foo') {
    const {data: resB} = useFetchB(resA)
    }
    }
    ```

    这样就不能抽象成 hook 了吧
    Pastsong
        8
    Pastsong  
       2022-09-16 00:51:31 +08:00
    useFetchAandB
    useFetchA
    useFetchB
    同时存在,想用啥用啥
    codehz
        9
    codehz  
       2022-09-16 00:54:32 +08:00 via iPhone
    @RRRSSS useSWR key 为 null 的时候不会发出请求,完美符合需求
    CptDoraemon
        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') {
    }
    })
    ```
    CptDoraemon
        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)
    }
    })
    ```
    codehz
        12
    codehz  
       2022-09-16 10:29:32 +08:00   ❤️ 1
    (再动态一点可以考虑包一层组件,虽然 hook 不能写条件,但是组件可以随便加
    做类似无限滚动的话还可以用 useSWRInfinite
    jjwjiang
        13
    jjwjiang  
       2022-09-16 11:17:11 +08:00
    B 既然依赖 A 的结果,那你定义 useFetchB 的时候给个入参就行了,这样所有用到 fetchB 的地方就必须传入 A 的结果

    如果 A 的查询和每个页面内容无关,那直接把 A 写到 useFetchB 里面去
    tonytonychopper
        14
    tonytonychopper  
       2022-09-17 00:36:31 +08:00
    @RRRSSS #7 这样写本来就会有坑,如果一定要这么写的话,不如在 useFetchB 内部做判断:

    function useFetchB
    if resA === 'foo' then do something
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5306 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 09:07 · PVG 17:07 · LAX 02:07 · JFK 05:07
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.