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

[Portal] Prepare deprecation of onRendered #16597

Merged
merged 4 commits into from
Jul 22, 2019

Conversation

oliviertassinari
Copy link
Member

@oliviertassinari oliviertassinari commented Jul 14, 2019

Starting now, people can use the ref instead of the onRendered prop. I think that we should remove it in v5.

Closes #16595

Related #16262 (comment).

@mui-pr-bot
Copy link

mui-pr-bot commented Jul 14, 2019

Details of bundle changes.

Comparing: b6182ce...0a78aca

bundle parsed diff gzip diff prev parsed current parsed prev gzip current gzip
@material-ui/core +0.02% 🔺 +0.01% 🔺 327,251 327,315 90,345 90,355
@material-ui/core/Paper 0.00% 0.00% 68,477 68,477 20,410 20,410
@material-ui/core/Paper.esm 0.00% 0.00% 61,761 61,761 19,177 19,177
@material-ui/core/Popper +0.20% 🔺 +0.20% 🔺 28,896 28,955 10,394 10,415
@material-ui/core/Textarea 0.00% -0.08% 5,534 5,534 2,369 2,367
@material-ui/core/TrapFocus 0.00% 0.00% 3,753 3,753 1,577 1,577
@material-ui/core/styles/createMuiTheme 0.00% -0.03% 16,156 16,156 5,816 5,814
@material-ui/core/useMediaQuery 0.00% 0.00% 3,098 3,098 1,310 1,310
@material-ui/lab +0.04% 🔺 +0.03% 🔺 141,699 141,758 43,813 43,824
@material-ui/styles 0.00% 0.00% 51,886 51,886 15,380 15,380
@material-ui/system 0.00% -0.25% 15,576 15,576 4,445 4,434
Button 0.00% -0.03% 79,711 79,711 24,358 24,350
Modal +0.12% 🔺 -0.04% 14,548 14,566 5,102 5,100
Portal +0.37% 🔺 -0.26% 3,471 3,484 1,568 1,564
Rating 0.00% -0.03% 70,267 70,267 22,068 22,062
Slider 0.00% -0.02% 75,096 75,096 23,311 23,306
colorManipulator 0.00% 0.00% 3,904 3,904 1,543 1,543
docs.landing 0.00% 0.00% 54,357 54,357 13,915 13,915
docs.main +0.01% 🔺 +0.01% 🔺 646,774 646,834 203,034 203,057
packages/material-ui/build/umd/material-ui.production.min.js +0.01% 🔺 0.00% 299,666 299,706 86,112 86,114

Generated by 🚫 dangerJS against 0a78aca

packages/material-ui/src/Portal/Portal.js Outdated Show resolved Hide resolved
packages/material-ui/src/Modal/Modal.js Show resolved Hide resolved
@oliviertassinari oliviertassinari force-pushed the modal-portal-ref branch 3 times, most recently from 445b94b to a9c5612 Compare July 16, 2019 08:42
@oliviertassinari oliviertassinari dismissed eps1lon’s stale review July 16, 2019 08:43

Updated to take the reviews into account


useEnhancedEffect(() => {
if (!disablePortal) {
setMountNode(getContainer(container) || document.body);
}
}, [container, disablePortal]);

React.useImperativeHandle(ref, () => mountNode || childRef.current, [mountNode]);
useEnhancedEffect(() => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why can't we use useImperativeHandle here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, probably with the new if(!node) logic. Will try +1

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh no, we can't. my bad. We still need to ignore the case where disablePortal is false.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you elaborate on that? Right now we handle a ref in the commit phase. If it's not possible to handle in the ref phase we need to name it differently. Otherwise it might create confusing bugs because it's expected to be updated during ref phase when it only happens during commit.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, with pleasure. The problem is in the case where disablePortal is true. The classic ref logic will try to set the value to the DOM node during the first ref phase. However, the useImperativeHandle logic also tries to set the value to null. It creates a conflict. I believe it can't work.

Also, I'm wondering does it care in which phase the ref value is set in our case? Previously, the ref was set to null during the ref phase (to accommodate SSR). Now, the ref isn't called. In both cases, people can't rely on the ref value to be defined, they have to handle this undefined case. They have to wait for the actual value, after the first commit, ref, layout and effect phases.

packages/material-ui/src/Portal/Portal.test.js Outdated Show resolved Hide resolved
@@ -65,6 +73,8 @@ Portal.propTypes = {
disablePortal: PropTypes.bool,
/**
* Callback fired once the children has been mounted into the `container`.
*
* This prop will be deprecated and removed in v5, the ref can be used instead.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* This prop will be deprecated and removed in v5, the ref can be used instead.
* You probably don't need this prop. Prefer to use callback refs on the component instead.

We haven't deprecated it yet.

Copy link
Member Author

@oliviertassinari oliviertassinari Jul 16, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The motivation for the "will be deprecate" is to create a sentiment of urgency for somebody relying on the prop but has a use case (we are not aware of) that can't rely on the ref. Do you think that we should still go for the "probably not"? I'm taking the time to ask because it's a broader topic, not specific to this occurrence. I can remember that the same method is used for withWidth. We had people opening an issue "Please don't deprecate withWidth" with some details (explaining why) consequent to the initial ultimatum.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could only find usage of it in Popper and that component has quite the complicated implementation for pretty simple behavior. I tried reducing the amount of logic to get a better hold of why we need onRendered instead of ref.

One part of the issue is the misnomer. Makes it hard to mentally "click" what this prop does.

I'd like to explore first why we need it in Popper and then we can go back to this one. As it looks like right now "you probably don't need it" is the better advise.

The motivation for the "will be deprecate" is to create a sentiment of urgency for somebody relying on the prop

That is not the why but the what. Why do you want to create a sense of urgency?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had forgotten about the Popper. I believe that the child div ref could be used instead. Would it work?

Why do you want to create a sense of urgency?

It incentives users to give us feedback sooner than if we wait to introduce the deprecation. it optimizes for learning. The sooner we have the information:

  • the less likely we will introduce a deprecation that we have to revert
  • the less likely somebody will use the prop and the better migration path going from v4 to v5

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what we gain by saying we will deprecate it if we're not sure about it. That can only hurt trust.

it optimizes for learning.

Could you elaborate on that?

Copy link
Member Author

@oliviertassinari oliviertassinari Jul 17, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I wasn't clear.

I think that we should first agree that removing the prop is the best long-term path. Do we?

Then, it's about waiting x months (x because we don't want people to feel too much code change pressure) before introducing the deprecation warning vs saying it right away and adding a warning only later on (it creates x months of additional learning opportunity).

I don't think that saying the prop will be deprecated and not deprecating it is worse than deprecating a prop and reverting.

So, if you think that we are not ready yet to commit to a deprecation, your suggestion is better without any doubts. If you think that we are good for deprecation, we have an opportunity to collect feedback x more months ("optimize for learning").

@oliviertassinari
Copy link
Member Author

I have removed the onRendered prop usage from the Popper.js component. It seems to work OK.

@oliviertassinari
Copy link
Member Author

Rebased.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: Portal The React component.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Portal: onRendered doesn't make sense if disablePortal is true
4 participants