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

Can not prevent portal unmounting when using ReactDOM.createPortal #10826

Closed
yesmeck opened this issue Sep 26, 2017 · 11 comments
Closed

Can not prevent portal unmounting when using ReactDOM.createPortal #10826

yesmeck opened this issue Sep 26, 2017 · 11 comments

Comments

@yesmeck
Copy link

yesmeck commented Sep 26, 2017

Previous comment #10143 (comment)

When we use unstable_renderIntoContainer implements portal, we can control when the portal unmount, this seems impossible when use createPortal, because when parent component unmount, portal will be unmount by React itself.

@yesmeck yesmeck changed the title Can not prevent portal unmount when using ReactDOM.createPortal Can not prevent portal unmounting when using ReactDOM.createPortal Sep 26, 2017
@Jessidhia
Copy link
Contributor

Unmounting on parent unmount looks like a feature, not a bug to me.

Perhaps doing something similar to what TransitionGroup does can work for your use case? When a child element is removed from TransitionGroup's children list it's not actually yet removed from the TransitionGroup's render result (so React doesn't unmount it), it just clones the last used props and sets a prop (in) to false. Once the child is ready to be removed, it calls the onExited prop callback.

@silentcloud
Copy link

+1

@benjycui
Copy link
Contributor

When a child element is removed from TransitionGroup's children list it's not actually yet removed from the TransitionGroup's render result (so React doesn't unmount it), it just clones the last used props and sets a prop (in) to false.

Actually, we cannot, we are maintaining a common UI component rc-dialog. We cannot prohibit other developers unmount our dialog, this is why it is a problem to us(And we know that it may not be a problem to others).

@lukeapage
Copy link

lukeapage commented Oct 27, 2017

This is a problem for us too.
The only work-around I can think of is to cache the dom and restore it after unmount and hope it doesn't flicker, which is pretty horrible.

@jaytrovare
Copy link

Having the same issue, and the only solution i've found is to not use createPortal :(

@jquense
Copy link
Contributor

jquense commented Oct 27, 2017

Hey y'all. I don't think the old behavior was actually supported, even if it sort of worked most of the time. The subtree component may have stayed rendered but it would be in an orphaned state, and likely to break if any update occurred on it, because the assumption was that the subtree is always actually parented. I've personally run into bugs where I've had the parent component unmount and then break something in the portal component on the next update cycle.

@lukeapage
Copy link

The best work-around I can think of is to do a ReactDOM.render in a asap to escape the react lifecycle stack trace.. then you have control over when the element is unmounted. we'll also need some magic to copy the context through, but I can't think of any other disadvantages?

How would the api for this look like? Would this be too inflexible?

ReactDOM.createPortal(children, element, (actualUnmount) => actualUnmount());

@gaearon
Copy link
Collaborator

gaearon commented Jan 6, 2018

It seems like the use case was not really supported in the past either and led to errors.

So I think we can’t say this is a “missing feature” of the portal API. It just isn’t as easily broken as the existing old API.

If you have specific API suggestions around this problem please create an RFC: https://github.com/reactjs/rfcs

Thanks!

@BiosBoy
Copy link

BiosBoy commented Jun 25, 2019

So, any solutions here? It's still a problem for me too... Cannot figure out how to prevent portal unmounts...

@timramone
Copy link

You usually want to prevent a portal parent from unmounting in a case, when you have some kind of a dropdown component, which should open a modal on click inside. Because it's a dropdown, it hides on click inside, and that triggers a modal to unmount too. We've fixed this problem by rendering hidden content of a dropdown with a display: none style. Maybe it'll help somebody.

@lucasreppewelander
Copy link

You usually want to prevent a portal parent from unmounting in a case, when you have some kind of a dropdown component, which should open a modal on click inside. Because it's a dropdown, it hides on click inside, and that triggers a modal to unmount too. We've fixed this problem by rendering hidden content of a dropdown with a display: none style. Maybe it'll help somebody.

This was exactly my issue but I handle it like this, I added a preventAutoClose prop to my dropdown items as when I click on the item I had an auto close function that ran on mouseup and a timeout of 50ms to auto close the dropdown when I clicked on it.

this was my solution:

const handleClick = () => {
    setTimeout(() => close && close(), 50);
};

useEffect(() => {
    if (preventCloseClick) {
        document.addEventListener('mouseup', handleClick);
    }

    return () => {
        if (preventCloseClick) {
            document.removeEventListener('mouseup', handleClick);
        }
    };
}, []);

so I just add preventCloseClick={true} to my <DropdownItem /> and it no longer unmounts unexpected..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests