Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] useModal #2302

Closed
Mrcxt opened this issue Aug 25, 2023 · 13 comments
Closed

[RFC] useModal #2302

Mrcxt opened this issue Aug 25, 2023 · 13 comments

Comments

@Mrcxt
Copy link

Mrcxt commented Aug 25, 2023

用于更加方便的调用modal、drawer等组件。

目前我是以单独的包提供。https://www.npmjs.com/package/nice-use-modal

因为是一个纯hooks,不绑定ui组件,因此想集成到ahooks中

@hchlq
Copy link
Collaborator

hchlq commented Aug 28, 2023

看上面 npm 包提供的例子,开发者还得使用 useModal 二次封装是吗,然后导出使用,感觉有点小麻烦

@Mrcxt
Copy link
Author

Mrcxt commented Aug 28, 2023

看上面 npm 包提供的例子,开发者还得使用 useModal 二次封装是吗,然后导出使用,感觉有点小麻烦

目前这个写法确实有点别扭,主要是props放置位置的问题。影响不大。

集成到ahooks中的写法做了修改:
image
多提供了一个写法:useModal(React.FC,props),使用时可以依据不同的场景使用不同的写法。

@liuyib
Copy link
Collaborator

liuyib commented Aug 29, 2023

这个 useModal 的返回值中,destory 看着就是 antd 弹框的 destoryOnClose 属性(其他组件库应该也有吧)。show/hide 和用 state 控制 visible/open 复杂度差不多。

我能感受到的好处是,用了这个 hook 后,会倒逼着用户把弹框相关的代码单独抽出去,然后导入传给 useModal,模块化更好些(相对而言)。

综上,我个人的看法,弹框相关的东西其实没有特别大的痛点,这个 useModal 简化了一些用法后,同时引入了等量复杂度的其他用法。感觉没太必要集成 ahooks 中。

不知道有没有更具有说服力的场景,能否给出代码看看,说明下 useModal 能解决较大的痛点呢~

@Mrcxt
Copy link
Author

Mrcxt commented Aug 29, 2023

我觉得有这么几点不同吧:

  1. destoryOnClose仅仅是销毁了modal内部的组件,而destory销毁的是使用modal的业务组件。不同点在于业务组件内部有很多业务状态,比如数据之类的,仅仅使用destoryOnClose是不够的,我们还需要手动对这些业务数据进行初始化,包括不限于:外部传入的数据、内部请求的数据、loading等。这些从业务逻辑上来说都是些繁琐且重复的步骤。
  2. 目前我们在使用modal封装业务组件的时候,调用的方式无非是那么几种:1. 外部定义useState(visible)、2. useRef、3. 内部预留点击插槽、4. render插入。前两种在我看来使用方式是一致的都不够雅观,且同一个页面有多个modal时会变得异常凌乱。第三种方式使用方式比前一种雅观,但是有个致命缺点就是一个按钮就得注册一个组件,假如我的组件有新建、编辑、查看等多种模式,那这种调用方式将是一种灾难。第四种缺点也很明显,丢失了上下文。
  3. 还有一点不同就是传统的modal业务组件,都需要将组件手动注册到页面当中,这样造成的问题就是当父组件渲染的同时,modal的业务组件也会被渲染,即使我们没有让modal显示。而在我的直觉里,应该是在执行show的时候才让我们的组件渲染,同时执行内部的useEffect。这一点也会造成业务代码逻辑上的不同。
  4. 我觉得我这个hook更像useAntdTable,都是为了让业务组件更加方便的使用。useModal解决的不是
  5. 命令式的调用更加简洁,大大简化了代码逻辑。

总结来说,我这个hook针对的不是modal,而是使用modal的业务组件。

其实我一直觉得在react中使用modal之类的的组件一直都是很不优雅的。我基本上也尝试过所有的风格,真心觉得目前的方式是最接近完美的。

其实我更建议你尝试一下我这个hook,真的很简洁,很提效。☺️☺️☺️

具体的代码示例如果需要我可以抽空搞个仓库写个例子对比一下各种写法的差异。

目前已经提交pr,里面有简单的示例场景。

@liuyib
Copy link
Collaborator

liuyib commented Aug 29, 2023

1, 3 点说的不错,同意。第 2 点,内部预留点击插槽 这种方式,不像你说的那么不堪吧:

假如我的组件有新建、编辑、查看等多种模式

一般编辑和查看会通过“弹框+Form”来实现,两者可以复用一个组件,通过加个 isEdit 参数区分。新建是另一个模态框。用 useModal 处理也得这样吧?

我目前看到的 useModal 好处是:1. 减少重置很多业务状态的操作。2. 倒逼用户封装 modal/drawer 组件的相关逻辑,整体不凌乱(代码凌乱问题,不用 useModal,用户自己封装也可以解决吧,只不过用了 useModal 会倒逼着封装)。

所以,确实需要你提供一些较为贴近真实业务的 demo 对比看一下,方便大家更好的做判断,辛苦哈~

另外,看看大佬们的意见 @crazylxr @hchlq @miracles1919 @li-jia-nan

@Mrcxt
Copy link
Author

Mrcxt commented Aug 30, 2023

假如我的组件有新建、编辑、查看等多种模式

一般编辑和查看会通过“弹框+Form”来实现,两者可以复用一个组件,通过加个 isEdit 参数区分。新建是另一个模态框。用 useModal 处理也得这样吧?

插槽模式的问题是:新建一个页面基本只有一个新建按钮,问题不大,但是编辑和查看大概率是出现在表格里,同一个页面就不只是一个,而是5个10个20个甚至更多了,这样就造成同一个业务组件在页面上会同时渲染十几二十次了(因为我看过我同事就是这么干的😓)。

useModal其实是复用了同一个组件,会有一个唯一key,多个状态模式下只需要共享同一个组件实例。

demo容我慢慢写来,我本身这个文字表达能力不太行😓哈哈,

@liuyib
Copy link
Collaborator

liuyib commented Aug 30, 2023

但是编辑和查看大概率是出现在表格里,同一个页面就不只是一个,而是5个10个20个甚至更多了,这样就造成同一个业务组件在页面上会同时渲染十几二十次了

是这样,这个场景下确实不适合再用插槽模式。


另外,useModal 的这个问题

image

需要让用户自己控制?用户怎么控制呢?给个代码示例看看。岂不是享受 useModal destroy 的优点的同时,又带来了新的负担。


demo容我慢慢写来,我本身这个文字表达能力不太行😓哈哈

表达能力很强了 👍,我只是尽量把能想到的地方都问出来,并不是你表达的问题。这样这个 RFC 才有参考意义

@Mrcxt
Copy link
Author

Mrcxt commented Aug 31, 2023

简单地写了一个文章对比了下各种方式的优缺点,以及useModal的使用demo和优缺点。
> 为什么要使用 useModal

@liuyib

@feong
Copy link

feong commented Sep 15, 2023

假如我的组件有新建、编辑、查看等多种模式

一般编辑和查看会通过“弹框+Form”来实现,两者可以复用一个组件,通过加个 isEdit 参数区分。新建是另一个模态框。用 useModal 处理也得这样吧?

插槽模式的问题是:新建一个页面基本只有一个新建按钮,问题不大,但是编辑和查看大概率是出现在表格里,同一个页面就不只是一个,而是5个10个20个甚至更多了,这样就造成同一个业务组件在页面上会同时渲染十几二十次了(因为我看过我同事就是这么干的😓)。

useModal其实是复用了同一个组件,会有一个唯一key,多个状态模式下只需要共享同一个组件实例。

demo容我慢慢写来,我本身这个文字表达能力不太行😓哈哈,

我就这么用的,每个“编辑”按钮被插到modal(ant-pro-component)里,放在table的每行记录里面。实际上的modal只在打开的时候才渲染到页面dom上,所以不必担心性能问题啦。

@LOWINC
Copy link

LOWINC commented Sep 15, 2023

https://github.com/eBay/nice-modal-react

和这个比较像

@Mrcxt
Copy link
Author

Mrcxt commented Sep 18, 2023

假如我的组件有新建、编辑、查看等多种模式

一般编辑和查看会通过“弹框+Form”来实现,两者可以复用一个组件,通过加个 isEdit 参数区分。新建是另一个模态框。用 useModal 处理也得这样吧?

插槽模式的问题是:新建一个页面基本只有一个新建按钮,问题不大,但是编辑和查看大概率是出现在表格里,同一个页面就不只是一个,而是5个10个20个甚至更多了,这样就造成同一个业务组件在页面上会同时渲染十几二十次了(因为我看过我同事就是这么干的😓)。
useModal其实是复用了同一个组件,会有一个唯一key,多个状态模式下只需要共享同一个组件实例。
demo容我慢慢写来,我本身这个文字表达能力不太行😓哈哈,

我就这么用的,每个“编辑”按钮被插到modal(ant-pro-component)里,放在table的每行记录里面。实际上的modal只在打开的时候才渲染到页面dom上,所以不必担心性能问题啦。

你错了,你说的model只在打开的时候才渲染是没错的,但是要注意,你说的只是model组件,而咱们这里说的是使用modal的业务组件。在你把业务组件插入到父组件的dom中时,子组件就已经渲染了,包括useEffect也已经执行了。

@Mrcxt
Copy link
Author

Mrcxt commented Sep 18, 2023

https://github.com/eBay/nice-modal-react

和这个比较像

是的,实现原理是差不多的,只是使用形式上差别比较大

@Wxh16144
Copy link

巧了,我前段时间也封装过一个类似的 hook,但是没有楼主的抽象,我这个和 antd 系列绑定了 https://github.com/Wxh16144/easy-antd-modal

@Mrcxt Mrcxt closed this as completed Jan 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants