Skip to content

[Tabs] Migrate to hooks#16427

Merged
oliviertassinari merged 4 commits into
mui:masterfrom
oliviertassinari:tabs-hook
Jul 5, 2019
Merged

[Tabs] Migrate to hooks#16427
oliviertassinari merged 4 commits into
mui:masterfrom
oliviertassinari:tabs-hook

Conversation

@oliviertassinari

Copy link
Copy Markdown
Member

Related to #15231.

@oliviertassinari oliviertassinari added the scope: tabs Changes related to the tabs. label Jun 29, 2019
@joshwooding joshwooding mentioned this pull request Jun 29, 2019
29 tasks
@oliviertassinari
oliviertassinari force-pushed the tabs-hook branch 4 times, most recently from f321919 to c1ced75 Compare June 30, 2019 14:22
@mui-pr-bot

mui-pr-bot commented Jun 30, 2019

Copy link
Copy Markdown

@material-ui/core: parsed: -1.06% 😍, gzip: -1.18% 😍

Details of bundle changes.

Comparing: 7050cf5...bf006b8

bundle parsed diff gzip diff prev parsed current parsed prev gzip current gzip
@material-ui/core -1.06% -1.18% 331,257 327,757 91,531 90,452
@material-ui/core/Paper -0.00% 0.00% 68,293 68,291 20,367 20,367
@material-ui/core/Paper.esm 0.00% -0.04% 61,574 61,574 19,164 19,157
@material-ui/core/Popper 0.00% 0.00% 28,942 28,942 10,407 10,407
@material-ui/core/Textarea 0.00% +0.04% 🔺 5,505 5,505 2,360 2,361
@material-ui/core/TrapFocus 0.00% -0.13% 3,753 3,753 1,579 1,577
@material-ui/core/styles/createMuiTheme 0.00% 0.00% 16,011 16,011 5,792 5,792
@material-ui/core/useMediaQuery 0.00% 0.00% 2,595 2,595 1,103 1,103
@material-ui/lab -0.09% -0.14% 140,155 140,022 43,484 43,423
@material-ui/styles 0.00% +0.01% 🔺 51,699 51,699 15,339 15,341
@material-ui/system 0.00% -0.02% 15,428 15,428 4,397 4,396
Button 0.00% +0.05% 🔺 84,442 84,442 25,732 25,744
Modal 0.00% +0.14% 🔺 14,533 14,533 5,094 5,101
Portal 0.00% 0.00% 3,471 3,471 1,574 1,574
Slider 0.00% +0.02% 🔺 74,994 74,994 23,296 23,300
colorManipulator 0.00% 0.00% 3,904 3,904 1,543 1,543
docs.landing 0.00% 0.00% 54,338 54,338 13,762 13,762
docs.main 0.00% 0.00% 647,028 647,028 203,913 203,914
packages/material-ui/build/umd/material-ui.production.min.js -1.12% -1.24% 303,536 300,130 87,156 86,077

Generated by 🚫 dangerJS against bf006b8

@oliviertassinari
oliviertassinari force-pushed the tabs-hook branch 2 times, most recently from f7efd43 to 78da4e8 Compare June 30, 2019 16:18
@oliviertassinari

oliviertassinari commented Jun 30, 2019

Copy link
Copy Markdown
Member Author
  • Migrate the tests to testing-library.

After migrating the Slider and the Tabs tests to testing-library, I have a bit more hindsight on the value this testing library bring. I definitely agree that the tests are in better shape. However, the migration task was time-consuming. I'm not sure that the gain worth it. We might have been better off spending this time on a different problem. I would propose that we prioritize removing the shallow tests over migrating the existing tests to testing-library first.

On a different note, I personally don't like the expect API. They are too many moving parts, take ).to.not.be.ok… . However, as Jest and testing-library are promoting it, we should migrate to it. I would encourage the usage of expect(B).to.equal(A) when possible. Maybe we could use a tool like https://github.com/devenbansod/jest-expect-codemod to automate the migration?

"normalize-scroll-left": "^0.2.0",
"popper.js": "^1.14.1",
"prop-types": "^15.7.2",
"react-event-listener": "^0.6.6",

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

One less dependency :).

@oliviertassinari
oliviertassinari force-pushed the tabs-hook branch 7 times, most recently from 714e1b6 to c867ede Compare June 30, 2019 22:16
@oliviertassinari
oliviertassinari marked this pull request as ready for review June 30, 2019 22:16
@eps1lon

eps1lon commented Jul 1, 2019

Copy link
Copy Markdown
Member

I would propose that we prioritize removing the shallow tests over migrating the existing tests to testing-library first.

Nobody proposed migrating the existing ones. I merely introduced another API in case tests need to be refactored for other reasons (strict mode, shallow removal etc).

take ).to.not.be.ok

Agree 💯 jest already identified this problem and reduced chainability to not only. Everything else is a single word improving grepability.

I wouldn't mind using jest-expect over chai's expect. I didn't even think about using it since I thought it was coupled with the test runner.

@oliviertassinari

oliviertassinari commented Jul 1, 2019

Copy link
Copy Markdown
Member Author

Nobody proposed migrating the existing ones. I merely introduced another API in case tests need to be refactored for other reasons (strict mode, shallow removal etc).

I believe that we (as a team) have introduced two ways of doing the same things (expect vs assert) and (enzyme vs testing-library). We should aim for simplicity, it's not OK to have two identical tools for the same job in the long run. However, we should also recognize that it's a necessary intermediate unideal state for improving the problems Material-UI tries to solve in the long term (providing the best possible React UI components).

So I think that we should progressively remove the assert and enzyme usage from the codebase. Does it make sense?

I wouldn't mind using jest-expect over chai's expect. I didn't even think about using it since I thought it was coupled with the test runner.

I would have a preference for jest expect as it might be more useful for people using our tests as inspiration. But, it's not very important from my perspective.

@oliviertassinari
oliviertassinari requested review from eps1lon and joshwooding and removed request for joshwooding July 2, 2019 17:23
@oliviertassinari

Copy link
Copy Markdown
Member Author

I will rebase the pull request to use the latest useEventCallback util and improve how the tests are written.

Comment thread packages/material-ui/src/Tabs/Tabs.test.js Outdated
Comment thread packages/material-ui/src/Tabs/Tabs.test.js
Comment thread packages/material-ui/src/Tabs/Tabs.js Outdated
marginBottom: null,
});
const valueToIndex = React.useRef();
valueToIndex.current = new Map();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is there a different with this vs const valueToIndex = React.useRef(new Map()) ?

@oliviertassinari oliviertassinari Jul 4, 2019

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I believe that the useRef first argument is used for the initial value (https://codesandbox.io/s/laughing-chandrasekhar-grk1r).
How will we reset the Map instance between two renders?

@joshwooding joshwooding Jul 4, 2019

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

If it needs to reset between renders it makes sense to do it this way. Should we not calculate it when the children prop changes instead of every render?

I guess it might break ssr though I haven’t had a close look

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

children prop (unless explicitly memoised) is typically written inline, so it's likely to be a new reference each time anyway 🙂

@oliviertassinari oliviertassinari Jul 5, 2019

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

So far, we are using the valueToIndex.current for:

  • Warning when providing a wrong value
  • Finding the selected tab item DOM node

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Finding the selected tab item DOM node

Should just attach a ref to it in v5. I think we allow custom tab components which means it would be breaking. If not then we can do it now.

@NMinhNguyen NMinhNguyen Jul 5, 2019

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actually thinking about it, for posterity & clarity maybe it's worth adding a comment to say why you're using a ref and not just a const valueToIndex = new Map() if you want it to reset every render?

@oliviertassinari oliviertassinari Jul 5, 2019

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Should just attach a ref to it in v5.

@eps1lon +1 for looking into what we can improve on the ref side in v5. It's something we could have implemented this way in the first place. For some reason, we didn't. To dive into why it wasn't done this way.

maybe it's worth adding a comment to say why you're using a ref and not just a const valueToIndex = new Map() if you want it to reset every render?

@NMinhNguyen Seems that we don't need the ref in the first place 🙃. I have just tried without, it's all right. Doing some more tests and committing.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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


const { tabsMeta, tabMeta } = this.getTabsMeta(value, theme.direction);
let left = 0;
window.addEventListener('resize', handleResize);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Probably doesn't matter because this is exactly equivalent to the old implementation but in the past we had issues in multi-window (window.open()) environments where window was referring to the parent window, and so the most bulletproof way was to do element.ownerDocument.defaultView to get the right window object (i.e. child not parent). I'm aware of the ownerWindow helper https://github.com/mui-org/material-ui/blob/89687f38cae750650555772ba4d821c9084d8dfc/packages/material-ui/src/utils/ownerWindow.js#L5 btw. It's just when I last looked at the implementation, I wasn't too sure why it falls back the way it does - parentView isn't a DOM property from what I can tell, nor is parentWindow from the original dom-helpers.

@oliviertassinari oliviertassinari Jul 5, 2019

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@NMinhNguyen Interesting, we should probably use the ownerWindow and ownerDocument helpers for all our global event listeners to better support multi-window like use cases. We don't have a very strong support yet.

The parentView logic originally comes from react-bootstrap/dom-helpers@43fcc24#diff-991ea3fb4ae30d4ee9eda4d4f6ea9595. I would propose we remove it.

The fallback argument is also never used, we can use the same approach as in the ownerDocument helper.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yeah, except it says parentWindow in dom-helpers 😅. Regardless, I don't think either of those properties exist: parentView, parentWindow. At least I couldn't find them when googling.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

parentWindow seems to only be suported by IE and opera. Probably super old and just c&p (see over-polyfilling)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ah you’re right. We could change parentView -> parentWindow or remove it altogether I guess.

@oliviertassinari oliviertassinari Jul 5, 2019

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

dom-helpers supports older browsers (IE 8) than we do (IE 11). If we can remove parentView, it's even better.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@NMinhNguyen Do you want to hit this with a pull request? 💥

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yes, will do. I can wait until you merge this PR and then change window -> ownerWindow as well.

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

Labels

scope: tabs Changes related to the tabs.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants