react-reverse-portal icon indicating copy to clipboard operation
react-reverse-portal copied to clipboard

Doesn't work when there is nested `portals.OutPoral`

Open loia5tqd001 opened this issue 4 years ago • 6 comments

Here is my code

<div>
  <portals.InPortal node={colorPortalNode}>
    <ColorProvider />
  </portals.InPortal>
  <portals.InPortal node={counterPortalNode}>
    <CounterProvider />
  </portals.InPortal>
  <portals.OutPortal node={colorPortalNode}>
    <portals.OutPortal node={counterPortalNode}>
      <button onClick={() => setPage((prev) => (prev + 1) % pages.length)}>
        Change Page
      </button>
      {pages[page] === "counter" && <Counter />}
      {pages[page] === "color" && <Color />}
    </portals.OutPortal>
  </portals.OutPortal>
</div> 

It seems only the inner portals.OutPortal takes effect whereas the outer doesn't. Aka:

  • Expect: Children can consume both CounterProvider and ColorProvider
  • Actual: Children can consume only CounterProvider

Here is the codesandbox of the problem

loia5tqd001 avatar Nov 10 '21 13:11 loia5tqd001

Woah, ok. Even passing children to OutPortal is pretty unusual, let alone trying to nest that! I can see how this might be useful for these kinds of provider use cases, but it's difficult to think through exactly how this should work. I'm not aware of any good reason why this wouldn't work, but I've never tested it before myself.

That said, I'd be happy to support this if it's possible to do so without adding too much extra complexity or breaking anything else.

Do you want to look into it? If you can just work out why it doesn't work already then that'd be very useful, and if you want to open a PR to fix it that'd be even better.

pimterry avatar Nov 10 '21 13:11 pimterry

Thanks for so quick reply @pimterry , actually before opening this issue I've tried to understand the code myself already, but there was no luck cause I'm still a noob lol. However let me try for several extra hours, if I still can't figure it out, perhaps I will need your need. Thanks.

loia5tqd001 avatar Nov 10 '21 13:11 loia5tqd001

Hmm it seems because the original design didn't expect OutPortal to have children in mind from the first place (as you stated above).

Instead of

App
  InPortal
    Constate
      useColor.Provider
  InPortal
    Constate
      useCounter.Provider
  OutPortal // for InPortal>Constate>useColor.Provider
    div
      OutPortal // for InPortal>Constate>useCounter.Provider
        div
          button
          Counter
            ...

here it is the actual component tree image

so the behavior instead of replacing OutPortal with InPortal, it brings all props (including children) from OutPortal to InPortal.


Just an update to you, I'll diagnose closer the code.

loia5tqd001 avatar Nov 10 '21 14:11 loia5tqd001

Hi @loia5tqd001 did you make any more progress here? Let me know if there's anything I can do to help.

pimterry avatar Nov 23 '21 11:11 pimterry

Hi @pimterry I really have no idea how to tweak the package to make it work for this use case 🤥 like I don't even know which question to ask, otherwise I asked already

loia5tqd001 avatar Nov 29 '21 13:11 loia5tqd001

Ok, fair enough. Yes, this use case isn't a priority for me right now, or for normal usage in general I think, but I would like to support it in future if possible. I don't think there's anything that would make this impossible, it's just a bit difficult to work out the details.

If you or anybody else does work out the underlying issue here and put a PR together to fix it, I'd be very happy to look at that. I'll leave this open for now.

pimterry avatar Nov 30 '21 12:11 pimterry