gorhom / react-native-portal

A simplified portal implementation for ⭕️ React Native & Web ⭕️.
MIT License
655 stars 36 forks source link

Context doesn't behave as expected #34

Open mrjackdavis opened 1 year ago

mrjackdavis commented 1 year ago

Hey!

I come from ReactDOM land where ReactDOM.createPortal exists and I see this library as the react-native alternative.

One key behaviour of ReactDOM.createPortal that I've come to expect, is that a rendered component that is portaled, maintains the context of where the element was defined.

See this issue for an example https://github.com/enesozturk/react-native-hold-menu/issues/82#issue-1403702172

I can also see confusion about this behaviour in #2, #3 and #31. The workaround seems to be to either re-order context providers. I have some cases where that is not feasible.

I dove into the source and understand why the behaviour is as it is.

@gorhom, have you thought about this previously? Is there a way to arrive at this behaviour without some sort of first-class implementation by react or react-native?

lightrow commented 1 year ago

Same issue for me. Took me a while to figure out what was wrong - i have a nested context provider overriding the parent one, but everything inside was using the wrong context values despite it being inside the nested provider.

noskovvkirill commented 1 year ago

From my understanding, that's currently not feasible in React Native. I've stumbled upon It's fine lib recently (https://github.com/pmndrs/its-fine) that has a useContextBridge hook. It looks like the library supports React Native, it might be interesting to experiment with it.

mrjackdavis commented 1 year ago

After a lot of digging, I found out that Modal is designed to be the replacement for React Native Portal which was deprecated long ago.

At first glance, I found this preposterous. But after some reflection, I think it makes sense. Portal, almost by design, is a DOM thing. And Modals aren't a first-class citizen in the DOM.

The opposite is true for RN. Modals are first class, Portals are a hack.

So I practically rewrote a couple of libraries I used that depend on react-native-portal to just use Modal. It works so much better.

I think this library can be misleading and is applied in situations where Modal is more appropriate. e.g. react-native-bottom-sheet/modal and react-native-hold-menu

@gorhom - you're the author of both react-native-bottom-sheet and this library. Have I missed something here? Why exactly have you used react-native-portal over Modal in react-native-bottom-sheet?

lightrow commented 1 year ago

portals have no "cost", they are a virtual thing. Modal is a tangible component that adds another layer to your UI and can cause some inconsistent/unexpected behaviour as it is dependant on both React Native's implementation and platform's own implementation which can change between OS versions

erquhart commented 1 year ago

Portals aren't a DOM thing, they're a hierarchy thing. The purpose of a portal is to enable declarative rendering from within a given component to a target that is higher up in the tree. If you just use Modal you'll likely end up using context and calling some sort of global-ish showModal() function to trigger it, and at best passing in a rendering function to make things somewhat declarative. It works, but it's implicit. I expect to define my modal in the relevant context and have a mechanism to render it elsewhere as an implementation detail.