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] Migrate to React hooks #15399

Merged
merged 4 commits into from
Apr 30, 2019
Merged

[Portal] Migrate to React hooks #15399

merged 4 commits into from
Apr 30, 2019

Conversation

gautam-pahuja
Copy link
Contributor

@gautam-pahuja gautam-pahuja commented Apr 18, 2019

This PR is a part of #15231

Breaking change

Only accept one element child when disablePortal is set.

packages/material-ui/src/Portal/Portal.js Outdated Show resolved Hide resolved
packages/material-ui/src/Portal/Portal.js Outdated Show resolved Hide resolved
packages/material-ui/src/Portal/Portal.js Outdated Show resolved Hide resolved
@joshwooding joshwooding mentioned this pull request Apr 18, 2019
29 tasks
@oliviertassinari oliviertassinari added component: Portal The React component. PR: needs revision The pull request can't be merged. More details is available on the code review or fails in the CI labels Apr 19, 2019
packages/material-ui/src/Portal/Portal.js Outdated Show resolved Hide resolved
packages/material-ui/src/Portal/Portal.js Outdated Show resolved Hide resolved
@gautam-pahuja
Copy link
Contributor Author

Hi @eps1lon
Another desperate attempt to make this work 😅 . Can you please review this one. Also, I am getting an issue with the commented line below, looks like parentElement always return null:

const setMountNode = () => {
    if (disablePortal) {
+      // mountNodeRef.current = ReactDOM.findDOMNode(ref).parentElement;

      return;
    }
    mountNodeRef.current = getContainer(container, getOwnerDocument(ref).body);
  };

Can you kindly point me in the right direction?
Thanks

@oliviertassinari oliviertassinari self-assigned this Apr 27, 2019
@mui-pr-bot
Copy link

mui-pr-bot commented Apr 27, 2019

@material-ui/core: parsed: -0.23% 😍, gzip: -0.10% 😍
@material-ui/lab: parsed: -0.61% 😍, gzip: -0.22% 😍

Details of bundle changes.

Comparing: 7869aac...8560282

bundle parsed diff gzip diff prev parsed current parsed prev gzip current gzip
@material-ui/core -0.23% -0.10% 311,022 310,298 84,579 84,491
@material-ui/core/Paper 0.00% -0.03% 67,623 67,623 20,121 20,115
@material-ui/core/Paper.esm 0.00% +0.08% 🔺 60,988 60,988 19,018 19,034
@material-ui/core/Popper -8.23% -4.89% 31,114 28,553 10,805 10,277
@material-ui/core/Textarea +0.15% 🔺 -0.04% 5,468 5,476 2,364 2,363
@material-ui/core/TrapFocus +0.32% 🔺 +0.13% 🔺 3,731 3,743 1,565 1,567
@material-ui/core/styles/createMuiTheme 0.00% 0.00% 15,943 15,943 5,777 5,777
@material-ui/core/useMediaQuery 0.00% +0.21% 🔺 2,106 2,106 974 976
@material-ui/lab -0.61% -0.22% 140,444 139,593 42,608 42,515
@material-ui/styles 0.00% -0.01% 51,151 51,151 15,149 15,148
@material-ui/system 0.00% 0.00% 11,765 11,765 3,923 3,923
Button 0.00% -0.03% 85,266 85,266 25,677 25,670
Modal -1.20% +1.32% 🔺 20,575 20,328 6,601 6,688
colorManipulator 0.00% 0.00% 3,904 3,904 1,543 1,543
docs.landing 0.00% 0.00% 51,531 51,531 11,368 11,368
docs.main -0.11% -0.05% 649,455 648,721 202,645 202,549
packages/material-ui/build/umd/material-ui.production.min.js -0.23% -0.13% 292,809 292,147 82,545 82,439

Generated by 🚫 dangerJS against 8560282

@oliviertassinari oliviertassinari removed the PR: needs revision The pull request can't be merged. More details is available on the code review or fails in the CI label Apr 27, 2019
@oliviertassinari oliviertassinari removed their assignment Apr 27, 2019
Copy link
Member

@oliviertassinari oliviertassinari left a comment

Choose a reason for hiding this comment

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

I have tried to complete the effort. It's ready for a second phase of reviews :)

@gautam-pahuja
Copy link
Contributor Author

Thanks a lot, @oliviertassinari for your help, really appreciate..!!
👍

@oliviertassinari oliviertassinari self-assigned this Apr 28, 2019
@oliviertassinari
Copy link
Member

oliviertassinari commented Apr 28, 2019

@gautam-pahuja I wish I could have guided you in the effort. But I didn't know how to handle the problem either, I only had a vague idea of what we could try and what could work. After hammering the problem for two hours, I could find a working solution. I'm excited about the -1.26% bundle size reduction of the modal as well as having a battle-tested implementation people can look at when migrating from Class to Hooks. We are not done yet. @eps1lon has a better 👀 than me for spotting issues in hooks logic.

const Portal = React.forwardRef(function Portal(props, ref) {
const { children, container, disablePortal, onRendered } = props;
const [mountNode, setMountNode] = React.useState(null);
const childRef = React.useRef(null);
Copy link
Member

Choose a reason for hiding this comment

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

Just curious, do these explicitly need to be null?

Copy link
Member

Choose a reason for hiding this comment

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

Reduces the number of overloads. React will set it to null when cleaning up so you end up with T | undefined | null if you don't initialize it. But I don't see a problem if you just compare weakly against nullish i.e. ref.current != null.

Copy link
Member

@oliviertassinari oliviertassinari Apr 29, 2019

Choose a reason for hiding this comment

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

Sebastian is right on spot. I have noticed the null / undefined difference in the tests that assert the ref values. It's inconsistent with the codebase. I'm reverting back to const childRef = React.useRef();. Thanks.

Copy link
Member

Choose a reason for hiding this comment

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

Hum, actually, I see a couple of different usage in the codebase:

  • React.useRef(undefined); x 1
  • React.useRef(null) x 10
  • React.useRef() x38

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, that’s why I asked :P As long as we stick to one I’m fine with either blank or null

Copy link
Member

Choose a reason for hiding this comment

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

If I understand Sebastian point, it's better in the demos to use null to reduce the number of types to write.

Copy link
Member

@oliviertassinari oliviertassinari Apr 29, 2019

Choose a reason for hiding this comment

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

I'm going with: null for the demos (improve TypeScript DX), nothing for the core (improve bundle size) and weak checks !=. It seems to be the already used standard, I only have to fix a few exceptions.

Copy link
Member

Choose a reason for hiding this comment

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

For refs to components I would prefer useRef(null). This is equivalent to the old createRef style prevalent in classes:

const createdRef       = React.createRef(); //    createdRef.current === null
const usedRef          = React.useRef(null); //      usedRef.current === null
const usedUndefinedRef = React.useRef(); // usedUndefinedRef.current === undefined

Copy link
Member

Choose a reason for hiding this comment

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

OK, good for me. The bundle size increase is negligeable. I will update the pull request to match createRef. It's simpler.

@oliviertassinari oliviertassinari removed their assignment Apr 30, 2019
@gautam-pahuja
Copy link
Contributor Author

Wow...Thanks a lot, @oliviertassinari ...This looks like way different to what I originally tried to do, I guess I have to work on my react-hooks skills before picking anything else up 😅 .

@joshwooding
Copy link
Member

joshwooding commented Apr 30, 2019

Wow...Thanks a lot, @oliviertassinari ...This looks like way different to what I originally tried to do, I guess I have to work on my react-hooks skills before picking anything else up 😅 .

@gautam-pahuja Portal was a deceptively hard component to convert to Hooks.

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

Successfully merging this pull request may close these issues.

7 participants