Why 95% of Modals should be Local (in React)

แชร์
ฝัง
  • เผยแพร่เมื่อ 3 ก.พ. 2025

ความคิดเห็น • 72

  • @jshstuff
    @jshstuff 8 หลายเดือนก่อน +13

    I wasn’t aware people were commonly considering having such engineered modal solutions with registries and such. local modal instances with a teleport have always seemed very elegant to me. as others have mentioned, the only tricky thing is handling multiple modal instances open at the same time.
    I really like this kind of video!

  • @1v512
    @1v512 8 หลายเดือนก่อน +2

    good introduction, with great understanding of modal's law, then deep into thinking React and ending with design principles. Outstanding content.

  • @MaxGJPanas
    @MaxGJPanas 8 หลายเดือนก่อน +12

    Great stuff. One thing you didn't touch on which comes up every now and then is how each solution handles modal-ception i.e. modals launching further modals on top of previous modals. e.g. a modal for accepting payment configuration which triggers another modal to confirm you really want to close it and exit the payment flow (bad example maybe, but you get the idea).

    • @ziriusph3395
      @ziriusph3395 8 หลายเดือนก่อน +2

      yes, I'm surprised it wasn't tackled at all. Do UI developers dodged building apps without having to implement multimodal?

    • @asadsalehumar1011
      @asadsalehumar1011 8 หลายเดือนก่อน +1

      Personally I tried to avoid nested modals. I think its bad for both developers and users. Bad DX & bad UX => should avoid. Maybe the solution is to change the first modal into a side panel and keep the second modal as a modal.

    • @ziriusph3395
      @ziriusph3395 8 หลายเดือนก่อน

      ​@@asadsalehumar1011 you have no choice if the UI/UX designer said it's how it should be built and it's the most scientific UI behaviour. Plus, mobile games are full of them, which means they are generally expected by the userland.

    • @eduardstefan6833
      @eduardstefan6833 7 หลายเดือนก่อน

      Portals solve this problem completely because modals just get appended inside the body at the end. So there's no use for z-index if you're using portals they just stack as expected.
      EDIT: They don't have to be appended on the body it's up to you but that's the usual approach with modals/popover.

    • @eugeneponomarov7429
      @eugeneponomarov7429 4 หลายเดือนก่อน

      In our commercial application I implemented modals with hook: hook is giving you the component to render, show and hide functions. Regarding your example I would just use 2 hooks: 1 will be for main modal and the second one for confirmation modal.

  • @prikshit8
    @prikshit8 8 หลายเดือนก่อน +13

    Underrated channel

  • @Imsofreshx
    @Imsofreshx 8 หลายเดือนก่อน +3

    Global modal store that handles stacking multiple modals, and each modal is impored locally where needed and shown imperatively using the store, that is the best approach after a lot of trial and error.

  • @xorlop
    @xorlop 8 หลายเดือนก่อน +6

    I think this is reasonable given that we now have the popover api. The actual rendering, not react, but html rendering, made creating modals themselves a real challenge. Maybe I am misremembering, but I think that was the main reason people chose to use portals for modals.

    • @rand0mtv660
      @rand0mtv660 8 หลายเดือนก่อน +3

      Portals are used so that you can avoid weird z-index issues because something later in DOM would overlap your modal. Rendering modal inside the document body, but still inside your JSX tree locally is great for composition and avoiding these issues.
      Same things were done with modals before React. You would usually place modal HTML before closing body tag so that modals render last in HTML.

  • @RMMMobil
    @RMMMobil 8 หลายเดือนก่อน

    does this logic also applies to React Native bottom sheets?

  • @virtual5754
    @virtual5754 8 หลายเดือนก่อน

    What about html dialog element? Does it help making modals in any way?

    • @UIEngineering
      @UIEngineering  8 หลายเดือนก่อน

      Yes! Whether you choose local or global, in both cases you would probably want to build some generic ModalWrapper, this is where you will want your Dialog element.

  • @diegoignacioalvarezespinoz3965
    @diegoignacioalvarezespinoz3965 8 หลายเดือนก่อน +1

    Why dont you use Zustand and use global modals?

    • @nhieljeff2156
      @nhieljeff2156 8 หลายเดือนก่อน

      exactly

    • @UIEngineering
      @UIEngineering  8 หลายเดือนก่อน

      You can, but that only solves prop-drilling and re-rendering and I've listed more arguments for local modals. I also said in the vid: use context OR some global state mgmt library. So go for Zustand if u rly need global modals, I only say that local modals often suffice :)

    • @UIEngineering
      @UIEngineering  8 หลายเดือนก่อน

      Zustand is even better than context imho

  • @yektadev
    @yektadev 8 หลายเดือนก่อน

    This is an interesting perspective. I don't use React, but I implemented a global modal architecture for a Compose-based app.
    Yes, it has all the mentioned downsides.
    However, in case of the global modals, you can look at your modal layer as a "Screen in another dimension". It can have it's own navigation logic just like the "main" screen and with that you can implement almost any imaginable use-case.
    Local is definitely easier to read and faster to grasp, but isn't suitable for complex use-cases. The classic "it depends".

  • @antonmaslyukov689
    @antonmaslyukov689 8 หลายเดือนก่อน +1

    Good video, but there is one step further, no open state, easier to chain, easier to handle returned value from modal, no element mounted until called, configurable from local component, no registration. It all comes to promise and createRoot, no portal needed, describe jsx once and then configure each modal as need locally.
    Make a global function for opening modal, that takes component and props as second argument, then get body, create and attach div, make this div as root and return promise, modal will get two props proceed - function to resolve promise with values, and close - function to reject promis with some kind of info/error. On close you just unmount root and remove created element and you done.
    As some of the modal can be reused, simply wrap open function, described previously, and make new function accept only props for modal, and there you have it, openConfirm, openInfo and many other.
    I have been working with this solution for quite a while, didn't notice any hiccup, the core took 28 lines with empty lines to space things up

  • @Brian-bo2fu
    @Brian-bo2fu 8 หลายเดือนก่อน

    I do agree your point on local modals can reduce rerender but how can you make sure that global modals and local modals are showed in sequence. With global modal management, you can implement queue to make sure your global modal never interrupts local modals. This is usually happen when you have to do some data polling for example: Polling every 30 mins to check if a new version released and show a version update reminder if there is new version

  • @haritssyah7434
    @haritssyah7434 8 หลายเดือนก่อน

    I like this type of video! Keep going!

  • @minyoungna6642
    @minyoungna6642 8 หลายเดือนก่อน

    I agree with Kent's approach hard - just encapsulate the modalic nature ( opening / closing ) inside the component. My only use case for global modal is nested structure where one modality may interfere with some modal in a different tree ( imagine a shopping cart that has a notification pop up, but shopping cart is only rendered )

  • @КепридеЛармо
    @КепридеЛармо 8 หลายเดือนก่อน

    The "big" problem of re-rendering the entire application due to calling a global component is solved by simply creating a separate instance of the React application for this. This worked effectively in different scenarios for me, in particular for Vue and for React

    • @mr.random8447
      @mr.random8447 6 หลายเดือนก่อน

      Sounds like performance hell

  • @LeprekusGaming
    @LeprekusGaming 8 หลายเดือนก่อน

    Hey! This is a really nice video very informative. What software do you use to edit and add assets like the arrow in 4:03

    • @UIEngineering
      @UIEngineering  8 หลายเดือนก่อน +1

      Thanks! ❤ I animate 95% with basic options in DaVinci Resolve. And this arrow is just 5 different arrows combined in some online gif converter 😅

  • @maixior123
    @maixior123 8 หลายเดือนก่อน

    where are you from? Your accent sounds kida polish?

  • @rand0mtv660
    @rand0mtv660 8 หลายเดือนก่อน +4

    5:54 And btw, as far as I know using Context doesn't re-render everything, it just re-renders child components that actually consume context using useContext hook.
    So if you have a tree like "Context > A > B > C" and component C is the only one consuming that Context, it will be the only child component in that tree that will re-render on that Context change. A and B will not re-render because of Context value change.

    • @Mankepanke
      @Mankepanke 8 หลายเดือนก่อน +5

      No, all children of the provider will rerender.
      A > FooProvider > B > C > use Foo.
      If foo changes, then the provider will rerender, which requires all nested render functions to run.

    • @rand0mtv660
      @rand0mtv660 8 หลายเดือนก่อน

      @@Mankepanke yeah sorry, I think you are right. I believe I've read somewhere long time ago that it will skip re-rendering immediate "children" so that means only components that use useContext will actually re-render.
      Might only be true in cases where immediate children are wrapped in React.memo(). Then React will see children have same props and won't re-render immediate "children", but only Context consumers.

    • @joelv4495
      @joelv4495 8 หลายเดือนก่อน

      @@Mankepankeyep. Some state libs like zustand have the affordance to subscribe to a subset of the global store.

    • @athulgeorge6744
      @athulgeorge6744 8 หลายเดือนก่อน +1

      @@Mankepanke Yes this is how it works, but I wonder if this will change with react forget.

    • @UIEngineering
      @UIEngineering  8 หลายเดือนก่อน

      ​@@athulgeorge6744 good point! I guess React Compiler will change the game.

  • @MarlonEnglemam
    @MarlonEnglemam 8 หลายเดือนก่อน

    local modals have always made sense to me! The only thing I dont like about them in react is the syntax that usually will be like: { isOpen && }
    for some reason I find it not elegant but at the end of the day it works fine so I stick with it!

  • @samyipsh5381
    @samyipsh5381 8 หลายเดือนก่อน

    that was a great explanation, thx!

  • @dulranga_2
    @dulranga_2 8 หลายเดือนก่อน

    this is great content !!

  • @vazus171
    @vazus171 8 หลายเดือนก่อน

    Personally I prefer modals to be global so that I simply open then from events, without need to define state and add component. Semantically it's not the best idea, but it's the easiest to use for me.
    Like that:
    const dialog = useDialog();
    Then in component's JSX:
    onClick={() => dialog.open()}
    useDialog() is a context wrapper that gives us open and close methods. Open method takes a component as a prop.

    • @UIEngineering
      @UIEngineering  8 หลายเดือนก่อน

      That's interesting take, but I think your preference comes from the power of habit. I mean, maybe you just feel more comfortable with imperative paradigm? React is declarative and imho it's better to fully embrace it's nature, or u will find yourself swimming against the tide too often. But that's just my opinion.

  • @Eghizio
    @Eghizio 8 หลายเดือนก่อน

    Good stuff. That's how I've been doing modals so I can now pat myself on the back :D

    • @UIEngineering
      @UIEngineering  8 หลายเดือนก่อน +1

      Haha, love it XD

  • @neociber24
    @neociber24 8 หลายเดือนก่อน

    I'm a little lost here, the children won't rerender if the ModalContext don't have children, take for example the react-hot-toast library, their provider don't have children, just store the state of the toasts to render.
    You can do the same with modals.

  • @naranyala_dev
    @naranyala_dev 8 หลายเดือนก่อน

    I just chose one of the reusable options, easy to put into another projects with less keystroke

    • @UIEngineering
      @UIEngineering  8 หลายเดือนก่อน

      If u need global modal, sure 👍

  • @MichaelSoriano
    @MichaelSoriano 8 หลายเดือนก่อน

    Wish I would've seen this earlier. I went the global route - and regretting it. Too complicated.

    • @UIEngineering
      @UIEngineering  8 หลายเดือนก่อน

      We learn the most on our mistakes 😁 Glad you have found my vid then, simplicity often (but not always) wins 😊

  • @anon5992
    @anon5992 8 หลายเดือนก่อน

    imagine quoting from someone who ordered other software developers to print their code in a coding video. nice vide btw local modals way to go

    • @UIEngineering
      @UIEngineering  8 หลายเดือนก่อน

      Good call out, maybe I shouldn't. But I think this quote is gold.

  • @bartlomiejuminski
    @bartlomiejuminski 8 หลายเดือนก่อน

    I don't like react but this video is high quality

  • @eugeneponomarov7429
    @eugeneponomarov7429 4 หลายเดือนก่อน

    I hate global modals and was advocating for local modals for years! People are putting modal's state in Redux because "everybody is doing that" or "that's how it should be done"...
    Also you forgot to mention that local modals will stop developers to write some shitty and convoluted code, since modal defined in redux store can be triggered in redux action and then redux actions are pure spaghetti with logic and render props altogether.
    Separation of concerns 💪

  • @maximroslow
    @maximroslow 8 หลายเดือนก่อน +3

    i was fired because of local modals don't do it

    • @UIEngineering
      @UIEngineering  8 หลายเดือนก่อน

      are u serious? 😅

  • @nhieljeff2156
    @nhieljeff2156 8 หลายเดือนก่อน +1

    yeah but zustand fixes this

    • @UIEngineering
      @UIEngineering  8 หลายเดือนก่อน

      It only fixes prop-drilling and re-rendering. But I agree that could be a good choice if you rly need global modal, probably better than using context

  • @mahmoudzakria6946
    @mahmoudzakria6946 8 หลายเดือนก่อน

    Use HTML5 Dialog element.

    • @UIEngineering
      @UIEngineering  8 หลายเดือนก่อน

      Yup, that can be used for the ModalWrapper component, I tried not to mix too many topics at once

  • @mpowereer6992
    @mpowereer6992 8 หลายเดือนก่อน

    POLSKA GUROM!!!

  • @justgame5508
    @justgame5508 8 หลายเดือนก่อน

    W take from Elon

  • @netssrmrz
    @netssrmrz 8 หลายเดือนก่อน

    good video, though it's a shame to see UIE talents wasted on react. regarding the topic; this is only an issue, in react, because of the ridiculous vdom and hierarchical component scope structure, in my opinion. in the end, when forced to work with react, i agree with the approach demonstrated.

    • @rand0mtv660
      @rand0mtv660 8 หลายเดือนก่อน +1

      This is not a React only issue. For example Vue has a Teleport component that is equivalent to React's Portal to render HTML outside of the component tree. So there if you want to use a local modal, you will have to render it locally the same in code and if you want it globally you will most likely have to do something similar, just different code because it's Vue.

    • @netssrmrz
      @netssrmrz 8 หลายเดือนก่อน +1

      @@rand0mtv660 ok so Vue has the same issue, again for the same reason. In the DOM There is no inherent limit on accessing components outside of the local component tree (Web Component API). These are artificial issues created by frameworks.

    • @UIEngineering
      @UIEngineering  8 หลายเดือนก่อน

      @netssrmrz thanks! Yup, I agree that's just the cost of using a framework. We can all go back to pre-framework era but I don't think it's good solution either. Everything has a cost.

    • @UIEngineering
      @UIEngineering  8 หลายเดือนก่อน

      And sorry to disappoint but I'm planning to cover a lot of React-related stuff for now. But I will definitely try to cover more general topics in web dev as well.