![]() | 1 chairuosen 2023-03-02 09:35:00 +08:00 应该是 2 ,担心性能的话,把 table 再封一个? |
2 leoskey 2023-03-02 09:42:25 +08:00 可以参考这篇文章《 React 组件性能优化:如何避免不必要的 re-render 》 https://mp.weixin.qq.com/s/z9GaB_48LHtL-if4mP-nZQ |
3 superedlimited 2023-03-02 09:48:02 +08:00 弹窗的 showState 放到 useMemo ,就不会导致 table 重新渲染了 |
4 AyaseEri 2023-03-02 09:56:58 +08:00 把弹窗封成一个独立组件,内部维护 showState ,对外暴露一个 toggle 接口,通过 ref 的形式让外部控制自己的显隐 或者是像 antd 那几个提示一样直接写成一个 function ,每次直接 call function 弹开弹窗 |
![]() | 5 ChefIsAwesome 2023-03-02 10:26:08 +08:00 via Android table 一个组件,dialog 一个组件。上面再套一层组件,相当于中间人沟通二者。 多个 dialog 也行。你想象一下 select ,实际也是弹窗。每行来一个,没人觉得奇怪。只要 dialog 关闭的时候,把 Dom 清空就行。 |
6 suzic 2023-03-02 10:32:37 +08:00 via Android 2 。会导致重新渲染么?不太懂 react ,在 vue 里边如果状态和表格无关的话,那部分是不会重新渲染的 |
![]() | 7 oppddd OP @suzic 会的,因为 vue 是将状态和副作用 render 进行了细粒度的绑定,react 不是,只要 setstate ,父组件子组件都跟着 rerender |
![]() | 8 oppddd OP @ChefIsAwesome 再套一个组件也会 rerender ,比如我点击一个按钮,要显示用户详情,那么弹窗就需要知道是什么 userId ,那就会导致状态提升,那么三个组件都会 rerender ; |
10 joesonw 2023-03-02 10:53:46 +08:00 via iPhone table 依赖的状态变化了才会刷新,例如有个按钮的 onClick 你直接原地手写的,每次都会变的,要用 useCallback 包起来。类似的检查检查,不会无故刷新的。 |
11 suzic 2023-03-02 10:55:27 +08:00 via Android @liuxsen93 我猜可以通过包装一个方法,每次调用时手动插入弹窗 dom ,每次用完自动销毁? vue 可以这样玩的,react 应该也可以,原理一样 |
![]() | 12 ChefIsAwesome 2023-03-02 10:57:47 +08:00 via Android @liuxsen93 你再琢磨琢磨。ID 存父组件上,传给 dialog ,table 只是改这个 ID ,不用收这个 ID 。 |
13 donlian 2023-03-02 10:58:19 +08:00 via iPhone 子组件用 React.memo 包一下,这样就不会 props 没变就触发 rerender 了 |
![]() | 14 linkopeneyes 2023-03-02 11:23:10 +08:00 ![]() 推荐一下我一直在用的维护弹窗的 hook https://github.com/eBay/nice-modal-react 通过这个插件你就可以只创建一个弹窗实例,并且不维护 showState ,切用命令式调用 |
![]() | 15 dsa999 2023-03-02 11:31:18 +08:00 我觉得弹出层最好放在外层,比如通过 portal 放到 body 下,这样就不会有样式污染的问题。 不过我目前的做法是使用 ReactDom 中的 createRoot 方法,在 body 下创建一个新的根节点处理弹出层。 优点: 1. 不会出现你说的重新渲染问题。 2. 不需要 showState ,通过 render/destroy 控制显隐即可。 缺点: 1. 由于是独立的两个根节点,会造成无法共享 context 等问题,不过可以通过 render 时把数据作为参数传入。 |
![]() | 16 yuuko 2023-03-02 11:42:33 +08:00 把弹窗放在 cell 组建,显示的时候挂载弹窗,不显示销毁,就不会存在多个实例了 |
![]() | 17 Ritr 2023-03-02 12:46:17 +08:00 当然是子路由啦,把弹框放到子路由里面就可以了 |
![]() | 18 monologue520 2023-03-02 13:55:46 +08:00 2 , 有时候是需要 table 重复渲染的,比如说 dialog 中操作改变了 table |
19 sunwang 2023-03-02 14:01:40 +08:00 这种情况还是倾向于在父级维护 showState ,像新增按钮这种倒是可以和弹窗封装到在一起 |
![]() | 20 linkopeneyes 2023-03-02 14:34:43 +08:00 @dsa999 其实有办法拿到上下文的,可以创建一个 ModalProvider 组件专门维护所有弹窗状态和渲染,用 context 传递状态和组件,然后拿这个组件包裹在根组件上,写一个 hook 传递 modal 给 ModalProvide 渲染,如果需要当前组件的上下文就把 ModalProvider 包在当前组件上,就能拿到上下文 |
![]() | 21 otakustay 2023-03-02 16:05:13 +08:00 把触发弹窗的 button 包个组件,里面管 show 状态,这样 table 就不会渲染了。至于多个弹窗实例,用{show && <Modal />}管呗,全局遮罩层一下,不就只有一个了么 |
22 jjwjiang 2023-03-02 16:16:45 +08:00 在 react hooks 里不应该恐惧一般情况下产生的 re-render 。整个组件级别的 re-render 依然会被 react 优化成只对弹窗部分 re-render |
![]() | 23 dsa999 2023-03-02 18:19:56 +08:00 @sjhhjx0122 嗯,不过大多数场景下 render 时传参也够用了。弹出层从交互上来看,本来就是处理额外的独立逻辑的嘛 |
![]() | 24 oppddd OP @sjhhjx0122 看了这个仓库,用着很舒服!大佬啊 |