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

Поділитися
Вставка
  • Опубліковано 2 чер 2024
  • Global vs Local Modals - it is a great architectural question that you should answer when coding your app.
    ⏱️Timestamps:
    00:00 - z-index stacking issue
    00:19 - React Portals
    00:27 - Global Modal Architecture Trend
    01:08 - Modal's Law
    01:22 - Problems with Local Modals
    02:10 - Global Modal comparison
    02:33 - "Dumb" Implementation
    03:09 - "Sophisticated" Implementation
    05:05 - Global vs Local Modal
    05:18 - Costs of Global Modal Architecture
    05:52 - Rendering Problem
    06:10 - Context Problem
    06:53 - Why Local Modals drawbacks are rly not that bad
    08:45 - When Global Modals are actually useful
    09:28 - The Rule of Least Power
    📖 Further Reading and Acknowledgments:
    - Nice Modal React - Announcement: / rethink-modals-managem...
    - Nice Modal React - GitHub: github.com/eBay/nice-modal-react
    - Elon Musk interview from Everyday Astrounat: • Starbase Tour with Elo...

КОМЕНТАРІ • 67

  • @jshstuff
    @jshstuff 13 днів тому +8

    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!

  • @MaxGJPanas
    @MaxGJPanas 14 днів тому +11

    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 13 днів тому +2

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

    • @asadsalehumar1011
      @asadsalehumar1011 13 днів тому

      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 13 днів тому

      ​@@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.

  • @InfinityFnatic
    @InfinityFnatic 13 днів тому +2

    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.

  • @1v512
    @1v512 13 днів тому +2

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

  • @xorlop
    @xorlop 14 днів тому +4

    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 14 днів тому +2

      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.

  • @prikshit8
    @prikshit8 14 днів тому +13

    Underrated channel

  • @haritssyah7434
    @haritssyah7434 14 днів тому

    I like this type of video! Keep going!

  • @LeprekusGaming
    @LeprekusGaming 13 днів тому

    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  6 днів тому +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 😅

  • @minyoungna6642
    @minyoungna6642 14 днів тому

    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 )

  • @samyipsh5381
    @samyipsh5381 13 днів тому

    that was a great explanation, thx!

  • @dulranga_2
    @dulranga_2 14 днів тому

    this is great content !!

  • @Brian-bo2fu
    @Brian-bo2fu 14 днів тому

    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

  • @yektadev
    @yektadev 12 днів тому

    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".

  • @user-zz7ko2vj2f
    @user-zz7ko2vj2f 12 днів тому

    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

  • @MarlonEnglemam
    @MarlonEnglemam 3 дні тому

    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!

  • @antonmaslyukov689
    @antonmaslyukov689 13 днів тому

    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

  • @user-ik7rp8qz5g
    @user-ik7rp8qz5g 12 днів тому

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

    • @UIEngineering
      @UIEngineering  6 днів тому

      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.

  • @vazus171
    @vazus171 12 днів тому

    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  6 днів тому

      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.

  • @maixior123
    @maixior123 4 дні тому

    where are you from? Your accent sounds kida polish?

  • @Eghizio
    @Eghizio 13 днів тому

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

  • @neociber24
    @neociber24 12 днів тому

    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.

  • @anon5992
    @anon5992 12 днів тому

    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  6 днів тому

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

  • @rand0mtv660
    @rand0mtv660 14 днів тому +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 14 днів тому +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 14 днів тому

      @@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 14 днів тому

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

    • @athulgeorge6744
      @athulgeorge6744 13 днів тому +1

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

    • @UIEngineering
      @UIEngineering  6 днів тому

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

  • @diegoignacioalvarezespinoz3965
    @diegoignacioalvarezespinoz3965 14 днів тому +1

    Why dont you use Zustand and use global modals?

    • @nhieljeff2156
      @nhieljeff2156 13 днів тому

      exactly

    • @UIEngineering
      @UIEngineering  6 днів тому

      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  6 днів тому

      Zustand is even better than context imho

  • @naranyala_dev
    @naranyala_dev 13 днів тому

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

  • @MichaelSoriano
    @MichaelSoriano 13 днів тому

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

    • @UIEngineering
      @UIEngineering  6 днів тому

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

  • @bartlomiejuminski
    @bartlomiejuminski 14 днів тому

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

  • @maximroslow
    @maximroslow 13 днів тому +3

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

  • @nhieljeff2156
    @nhieljeff2156 13 днів тому +1

    yeah but zustand fixes this

    • @UIEngineering
      @UIEngineering  6 днів тому

      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

  • @mpowereer6992
    @mpowereer6992 13 днів тому

    POLSKA GUROM!!!

  • @mahmoudzakria6946
    @mahmoudzakria6946 13 днів тому

    Use HTML5 Dialog element.

    • @UIEngineering
      @UIEngineering  6 днів тому

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

  • @justgame5508
    @justgame5508 13 днів тому

    W take from Elon

  • @netssrmrz
    @netssrmrz 14 днів тому

    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 14 днів тому +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 14 днів тому +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  6 днів тому

      @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  6 днів тому

      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.