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

react 怎么给每个组件都加上刷新按钮?感觉这种需求很难搞。。修改 antd 的源码能行吗

  •  
  •   790002517zzy ·
    zzy-life · 2024-05-14 10:29:50 +08:00 · 4181 次点击
    这是一个创建于 366 天前的主题,其中的信息可能已经有所发展或是发生改变。
    比如这样的需求,有什么比较好的方式吗?刷新当前组件的方式也可以。


    组件都是用 antd 的 Modal 弹出来的,只要刷 Modal 就行:
    33 条回复    2024-05-15 13:01:29 +08:00
    rookie2luochao
        1
    rookie2luochao  
       2024-05-14 10:47:07 +08:00
    看不到你的图片,组件都加上刷新是什么意思,从来没遇到过所有组件刷新,你的组件指的是业务组件,还是要包含 UI 组件,如果是组件里面的接口有联动,可以用 rxjs 构造成可观察对象,或者用 react-query 来做组件之间的接口联动

    demo: https://github.com/rookie-luochao/create-vite-app-cli/tree/master/template-react-ts#%E8%B0%83%E7%94%A8%E6%8E%A5%E5%8F%A3react-query-%E6%94%AF%E6%8C%81%E8%87%AA%E5%8A%A8loading%E5%92%8C%E6%8E%A5%E5%8F%A3%E8%AF%B7%E6%B1%82%E8%81%94%E5%8A%A8
    mxT52CRuqR6o5
        2
    mxT52CRuqR6o5  
       2024-05-14 10:57:53 +08:00
    写个能传 children 的组件
    790002517zzy
        3
    790002517zzy  
    OP
       2024-05-14 11:04:29 +08:00
    @rookie2luochao 看不到图应该是梯子问题 只需要刷新最前面的组件就行,类似于刷新 z-index 最高的 Modal 即可(目的是刷新数据)


    @mxT52CRuqR6o5 这样的话就需要改每个页面了
    rookie2luochao
        4
    rookie2luochao  
       2024-05-14 11:07:12 +08:00
    @790002517zzy 你的目的是刷新数据的话,可以看看我发的那个链接,那个库能很好的处理跨组件之间的接口联动刷新问题,你也可以用 rxjs 实现
    douxc
        5
    douxc  
       2024-05-14 11:07:20 +08:00
    呃,modal 弹出来的时候请求一次数据?那就在 modal 显示的时候处理一下,useEffect 监听 open/close 状态,发现是显示就去获取数据
    790002517zzy
        6
    790002517zzy  
    OP
       2024-05-14 11:09:24 +08:00
    比如如果用 iframe 实现 Modal 可以使用 reload 让浏览器刷新(图 1 就是这样实现的)
    但是组件形式如果用 reload 会导致这个 url 刷新,而需求只需要刷新 Modal
    790002517zzy
        7
    790002517zzy  
    OP
       2024-05-14 11:10:25 +08:00
    @douxc modal 弹出来后,数据会变动(其他用户操作了这个数据),所以用户需要一个刷新按钮刷新当前 modal 中的数据
    790002517zzy
        8
    790002517zzy  
    OP
       2024-05-14 11:15:15 +08:00
    @rookie2luochao RxJS 好像可以,看起来像是会自动更新数据?可我很多个页面都用了 modal ,这样改的话也需要每个页面都去改。 还不如重新封装 modal 组件了
    googleaccount
        9
    googleaccount  
       2024-05-14 11:30:28 +08:00
    追求数据实时性 考虑用 websocket ?
    790002517zzy
        10
    790002517zzy  
    OP
       2024-05-14 11:32:36 +08:00
    @googleaccount 不是实时性,就是用户想点一下就看最新的数据,而不是 F5 刷新还要点半天才能打开这个 modal
    CHTuring
        11
    CHTuring  
       2024-05-14 11:35:16 +08:00
    1 、如果只是数据数据更新的话,每次 modal 关闭的时候销毁内部的组件就可以实现。
    2 、如果是希望复用,一个高阶函数就能实现
    gaogang
        12
    gaogang  
       2024-05-14 11:39:07 +08:00
    组件内部可变化的数据是拿不到吗?
    直接用 props 传进去的话,传入的值变了的话,组件不是会就会重新渲染了吗
    ZSeptember
        13
    ZSeptember  
       2024-05-14 11:41:20 +08:00
    基于 antd 的 modal 封装一个 modal ,固定给 modal 新增一个 refresh 按钮和 refresh 的 action 。

    refresh 的默认行为可以是将 children 替换为一个 loading 页面,然后再重新加载 children ,就会触发 children 重新加载吧。
    leroy20317
        14
    leroy20317  
       2024-05-14 11:49:36 +08:00
    Modal.useModal() modal 提供的 hooks 上下文可以用不?
    ZZITE
        15
    ZZITE  
       2024-05-14 11:55:33 +08:00
    refresh 数据不就行了吗?你的数据是在哪一层,通过什么形式获取的?
    我举个例子,假设是在 modal 内部自己通过 react-query 这种请求管理工具获取的数据,那么在刷新按钮点击时执行一次 refetch 或者 invalidateQueries ,modal 内的数据就更新了。可以通过高阶组件的形式,把所有 modal 都包裹一下,统一加上刷新按钮的功能。
    leroy20317
        16
    leroy20317  
       2024-05-14 11:56:09 +08:00
    要是只是想重新 render 一次,const [, setState] = useState({}); setState({}) 也可以的
    veveue
        17
    veveue  
       2024-05-14 13:16:47 +08:00
    这就要看 modal 获取数据的逻辑怎么写的了
    cydian
        18
    cydian  
       2024-05-14 13:45:59 +08:00
    swr
    ColdBird
        19
    ColdBird  
       2024-05-14 14:04:29 +08:00
    整个组件包一下不就得了,按你说的只对 modal 做操作那不是简单的很,不至于上升到对全部 Antd 组件的处理。
    * 方案 1:props 里只传 data ,这样内部不关心 data 的变更,外层 refresh 之后自己请求数据,内层更新 UI
    * 方案 2:props 里传 onLoad 作为加载回调、payload 作为触发器,监听 payload 的变化调用 onLoad 请求数据,再这个基础上抽象一下,不难实现
    790002517zzy
        20
    790002517zzy  
    OP
       2024-05-14 14:10:10 +08:00
    就是想刷新 Modal 嵌套的组件...这样的话就达到了刷新数据的效果
    上面说的从数据获取上着手就要每个页面都要改,工作量太大
    kinghly
        21
    kinghly  
       2024-05-14 14:22:36 +08:00 via Android
    最简单就是关闭时销毁 modal
    790002517zzy
        22
    790002517zzy  
    OP
       2024-05-14 14:25:19 +08:00
    @kinghly 是的,destroyOnClose 属性,但是不够理想,用户需要关闭 modal 重新打开才可以
    @leroy20317 写在 html 中的
    @ZSeptember refresh 怎么刷新(或者逻辑是关闭打开) modal 中的组件呢?
    vanchKong
        23
    vanchKong  
       2024-05-14 14:36:28 +08:00
    写个组件,传入刷新方法就行了呗
    Mexion
        24
    Mexion  
       2024-05-14 14:38:30 +08:00
    Modal 的内容不是你自己传进去的吗,你自己搞个有刷新按钮的高阶组件,需要刷新的组件套进去就行了
    790002517zzy
        25
    790002517zzy  
    OP
       2024-05-14 14:42:45 +08:00
    update 方法可以更新 modal 窗口,问题来了,怎么获取它?可以在根页面直接通过 ref 拿到顶层 modal 的 dom 吗?
    gaoxiu
        26
    gaoxiu  
       2024-05-14 14:43:07 +08:00
    @790002517zzy #20 意思是 只需要刷新 Modal 内的组件?那么这个组件的数据是自治的吧?是的话就挺简单的:
    1. 用 Modal 的 closeIcon 重新定义关闭图标,借用这个 api 添加一个刷新按钮(记得阻止刷新按钮的冒泡事件)
    2. 需要刷新的子组件添加 key 属性,每次刷新的时候更新这个 key
    theohateonion
        27
    theohateonion  
       2024-05-14 15:00:30 +08:00
    噢,你不想改每个子组件但是又想给所有用了 modal 的组件加上刷新功能。26 楼的方法可行,刷 key 就可以了。

    能解决问题,但是也是给自己埋坑。万一哪个组件又不想自动刷新了呢。。

    最好的办法还是重新封装一个 modal 组件,是否需要刷新这个标志由 modal 传入子组件,子组件自己决定刷不刷。
    DesnLee
        28
    DesnLee  
       2024-05-14 15:04:03 +08:00
    给要刷新的组件树最顶层的组件一个 key ,改变这个 key 组件内部就会重新渲染
    790002517zzy
        29
    790002517zzy  
    OP
       2024-05-14 15:10:17 +08:00
    @gaoxiu 感谢好像搞定了,把组件替换掉,更换下引用就行
    谢谢大家
    withoutxx
        30
    withoutxx  
       2024-05-14 15:12:12 +08:00
    试了下骚操作,不要在真实项目这么玩,Modal.useXXX 应该都会失效
    https://stackblitz.com/edit/react-f4out2


    790002517zzy
        31
    790002517zzy  
    OP
       2024-05-14 15:56:57 +08:00
    新问题...把所有的 Modal 改成 26#之后,节点直接无限刷新了,页面不出来
    790002517zzy
        32
    790002517zzy  
    OP
       2024-05-14 16:06:03 +08:00
    没事了没事了,一键替换的时候重复循环了
    natamox
        33
    natamox  
       2024-05-15 13:01:29 +08:00
    setState({})
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4693 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 09:49 · PVG 17:49 · LAX 02:49 · JFK 05:49
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.