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

[TreeView] Improve node registration and fix other issues #21574

Merged
merged 8 commits into from
Jul 3, 2020

Conversation

joshwooding
Copy link
Member

@joshwooding joshwooding commented Jun 25, 2020

Closes #20092 (Including #20147 here to prevent merge conflicts)

  • Needed to update the test to cover the bug and change the fix - the previous one wouldn't have worked due to children not being set when node is collapsed. Thanks @tonyhallett. There's another change I want to make that will tidy this up even more.

@joshwooding joshwooding added new feature New feature or request component: tree view TreeView, TreeItem. This is the name of the generic UI component, not the React module! labels Jun 25, 2020
@mui-pr-bot
Copy link

mui-pr-bot commented Jun 25, 2020

@material-ui/lab: parsed: +1.00% , gzip: +1.11%

Details of bundle changes

Generated by 🚫 dangerJS against e120da9

@oliviertassinari
Copy link
Member

oliviertassinari commented Jun 25, 2020

@joshwooding I know it's a draft. When you can get the chance, if you could like the issue(s) the change aims to solve, it would be 👌

@eps1lon Could something be wrong in the size comparison report? The diff seems inverted, it seems we add more code than we remove in the pull request.

Capture d’écran 2020-06-26 à 00 03 17

https://mui-dashboard.netlify.app/size-comparison?buildId=10610&baseRef=next&baseCommit=57322a9c0ce51b3fc841216eaa7ae7d7d8da0f70&prNumber=21574

Edit @eps1lon: Resolve size comparison issue in https://github.com/eps1lon/mui-contributor-dashboard/pull/9

@joshwooding joshwooding changed the title [TreeView] Improve node registration [TreeView] Improve node registration and fix other issues Jun 26, 2020
@joshwooding
Copy link
Member Author

I've tidied up tests as part of another change.

@joshwooding joshwooding force-pushed the descendants-tree-view branch 2 times, most recently from 48c5de8 to cf75994 Compare June 27, 2020 00:56
@joshwooding joshwooding marked this pull request as ready for review June 27, 2020 00:57
@@ -7,6 +7,7 @@ import Collapse from '@material-ui/core/Collapse';
import { fade, withStyles, useTheme } from '@material-ui/core/styles';
import { useForkRef } from '@material-ui/core/utils';
import TreeViewContext from '../TreeView/TreeViewContext';
import { DescendantProvider, useDescendant, useDescendantsInit } from '../TreeView/descendants';
Copy link
Member Author

@joshwooding joshwooding Jun 27, 2020

Choose a reason for hiding this comment

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

Using descendants allows us to get tree items in the correct order without reading children' props meaning we aren't so fragile and allow wrapped TreeItems.

@@ -990,27 +992,27 @@ describe('<TreeItem />', () => {
fireEvent.keyDown(getByTestId('three'), { key: 'ArrowDown', shiftKey: true });

expect(getByTestId('four')).toHaveFocus();
expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(2);
expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(2);
Copy link
Member Author

Choose a reason for hiding this comment

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

Consistency changes.

@@ -864,10 +863,13 @@ describe('<TreeItem />', () => {

fireEvent.keyDown(getByTestId('one'), { key: '*' });

expect(toggleSpy.args[0][1]).to.have.length(3);
Copy link
Member Author

Choose a reason for hiding this comment

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

We need to check the change handler here because eight will never have aria-expanded set due to a check when applying that attribute.


for (let i = 0; i < arr1.length; i += 1) {
if (arr1[i] !== arr2[i]) return true;
// To replace with Object.values() once we stop IE 11 support.
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 didn't forget this time 😆 I'm sure I missed something else though :P

Copy link
Member

Choose a reason for hiding this comment

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

Do we really need Object.values? Isn't it trivial to do

-Object.values(obj).forEach(value => {
+Object.keys(obj).forEach(key => {
+  const value = obj[key]
})

@@ -77,6 +80,12 @@ const TreeView = React.forwardRef(function TreeView(props, ref) {
state: 'selected',
});

const getChildren = (id) =>
Copy link
Member Author

Choose a reason for hiding this comment

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

Bit worried about performance here due to all the looping. Something to think about I guess.

if (nodeIndex !== -1 && nodeIndex + 1 < visibleNodes.current.length) {
return visibleNodes.current[nodeIndex + 1];
// If expanded get first child
if (isExpanded(id) && getChildren(id).length > 0) {
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've got some changes planned in the future which mean we won't have to check children length here.

nodeMap.current[childId] = { ...currentChildMap, parent: id, id: childId };
});
};
nodeMap.current[id] = { id, index, parentId, expandable };
Copy link
Member Author

Choose a reason for hiding this comment

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

Registering is a lot more simple now.

}
});
nodeMap.current = newMap;
cleanUpNodeMap(nodes);
Copy link
Member Author

Choose a reason for hiding this comment

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

unregistering nodes has also been simplified a lot.

);

const mapFirstChar = (id, firstChar) => {
firstCharMap.current[id] = firstChar;
};

const prevChildIds = React.useRef([]);
Copy link
Member Author

@joshwooding joshwooding Jun 27, 2020

Choose a reason for hiding this comment

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

Bye-bye, fragile code 👋

@@ -62,9 +62,7 @@ describe('<TreeView />', () => {
);
});

// should not throw eventually or with a better error message
// FIXME: https://github.com/mui-org/material-ui/issues/20832
it('crashes when unmounting with duplicate ids', () => {
Copy link
Member Author

Choose a reason for hiding this comment

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

🎉

import PropTypes from 'prop-types';

/** Credit: https://github.com/reach/reach-ui/blob/86a046f54d53b6420e392b3fa56dd991d9d4e458/packages/descendants/README.md
* Modified slightly to suit our purposes.
Copy link
Member Author

@joshwooding joshwooding Jun 27, 2020

Choose a reason for hiding this comment

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

Modifications are to allow the parentId to be read through this context. If we wanted to use the source we could use a second context. Not sure about IE11 support though.

@joshwooding joshwooding added the bug 🐛 Something doesn't work label Jun 28, 2020
@joshwooding
Copy link
Member Author

Work here is still relevant but reconsidering descendants is something to think about after the focus change: #21613 (comment)

@eps1lon

This comment has been minimized.


for (let i = 0; i < arr1.length; i += 1) {
if (arr1[i] !== arr2[i]) return true;
// To replace with Object.values() once we stop IE 11 support.
Copy link
Member

Choose a reason for hiding this comment

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

Do we really need Object.values? Isn't it trivial to do

-Object.values(obj).forEach(value => {
+Object.keys(obj).forEach(key => {
+  const value = obj[key]
})

packages/material-ui-lab/src/TreeView/TreeView.js Outdated Show resolved Hide resolved
packages/material-ui-lab/src/TreeView/TreeView.js Outdated Show resolved Hide resolved
packages/material-ui-lab/src/TreeView/TreeView.js Outdated Show resolved Hide resolved
packages/material-ui-lab/src/TreeView/TreeView.js Outdated Show resolved Hide resolved
packages/material-ui-lab/src/TreeView/descendants.js Outdated Show resolved Hide resolved
@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged label Jul 2, 2020
@joshwooding joshwooding requested a review from eps1lon July 3, 2020 00:39
@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged label Jul 3, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐛 Something doesn't work component: tree view TreeView, TreeItem. This is the name of the generic UI component, not the React module! new feature New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[TreeView] Unmount crashes React [TreeView] Incorrect expanded logic
4 participants