简化 react hook 的方法? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
RRRSSS
V2EX    React

简化 react hook 的方法?

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

    我的场景是这样的:

    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     Solana     5560 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 08:57 PVG 16:57 LAX 01:57 JFK 04:57
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86