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

fix(component): performance improvements for Dropdown/Select components #475

Merged
merged 29 commits into from
Jan 20, 2021

Conversation

jorgemoya
Copy link
Contributor

@jorgemoya jorgemoya commented Dec 1, 2020

What

Long time coming, but we noticed every single item would rerender whenever hovering an option, so we knew performance could be improved.

This changes fix that by memoizing the props that were triggering a rerender, thus only items with true changes will rerender. I added some props to some components for feature parity (like groups to MultiSelect). A lot of things were moved around, hoping this helps with clarity of these components.

Some area of opportunity:

  • Typescript stuff. Having some issues with this and had to drop some as. Let me know if we can fix them some other way!
  • When selection happens in MultiSelect component, all items rerender.
  • All wrappers rerender atm thanks to popper when scrolling, FIXED.
  • In the future, I would like to take the time to transform the MultiSelect component to use useMultipleSelection downshift hook.

Screenshots

Kapture 2020-12-01 at 14 56 29

@jorgemoya jorgemoya requested a review from a team December 1, 2020 20:55
@jorgemoya jorgemoya requested a review from a team as a code owner December 1, 2020 20:55
@jorgemoya jorgemoya force-pushed the select-performance branch 3 times, most recently from aff89fc to d6b06b9 Compare December 8, 2020 15:37
}
</Reference>
isValidElement(toggle) &&
cloneElement<React.HTMLAttributes<any> & React.RefAttributes<any>>(toggle as any, {
Copy link
Contributor

Choose a reason for hiding this comment

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

This can be reduced to this:

Suggested change
cloneElement<React.HTMLAttributes<any> & React.RefAttributes<any>>(toggle as any, {
cloneElement(toggle, {

import { StyledBox } from './styled';
import { DropdownItem, DropdownLinkItem, DropdownProps } from './types';

import { DropdownItemGroup } from '.';
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's import this from ./types above.

isAction = false,
...props
}) => {
type Items = DropdownItem | DropdownLinkItem | SelectOption<unknown> | SelectAction;
Copy link
Contributor

Choose a reason for hiding this comment

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

I think you can add a generic to Items

Suggested change
type Items = DropdownItem | DropdownLinkItem | SelectOption<unknown> | SelectAction;
type Items<T> = DropdownItem | DropdownLinkItem | SelectOption<T> | SelectAction;


export const List = memo(
forwardRef<HTMLUListElement, ListProps>((props, ref) => <StyleableList {...props} forwardedRef={ref} />),
forwardRef<HTMLUListElement, ListProps<unknown>>((props, ref) => <StyleableList {...props} forwardedRef={ref} />),
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we add a comment on why we need this unknown?

packages/big-design/src/components/List/styled.tsx Outdated Show resolved Hide resolved
packages/big-design/src/components/Select/Select.tsx Outdated Show resolved Hide resolved
packages/big-design/src/components/Select/styled.tsx Outdated Show resolved Hide resolved
Copy link
Contributor

@chanceaclark chanceaclark left a comment

Choose a reason for hiding this comment

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

Looks good, one last 🍹 comment. I would also get 1 more set of 👀 on this.

@@ -3,7 +3,7 @@ import { theme as defaultTheme } from '@bigcommerce/big-design-theme';
import { hideVisually } from 'polished';
import styled, { css } from 'styled-components';

import { StyledButton } from '../Button/styled';
import { StyleableButton } from '../Button/Button';
Copy link
Contributor

Choose a reason for hiding this comment

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

🍹

Suggested change
import { StyleableButton } from '../Button/Button';
import { StyleableButton } from '../Button/private';

@jorgemoya
Copy link
Contributor Author

We're looking for one more set of eyes @bigcommerce/frontend

{
name: 'eventListeners',
options: {
scroll: isOpen,
Copy link
Member

Choose a reason for hiding this comment

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

nice

@jorgemoya jorgemoya added the do not merge Don't merge this PR! label Dec 14, 2020
@jorgemoya
Copy link
Contributor Author

There is an issue with Downshift and memoized components. I have opened a PR for a potential fix, I would advise not to merge until the fix is released. downshift-js/downshift#1205

@jorgemoya jorgemoya removed the do not merge Don't merge this PR! label Jan 20, 2021
@jorgemoya jorgemoya merged commit b5167f9 into bigcommerce:master Jan 20, 2021
@jorgemoya jorgemoya deleted the select-performance branch January 20, 2021 20:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants