Merge pull request #5957 from influxdata/fix/dropdown_anchor_follow

fix(ui): optimize dropdown menu to avoid items re-rendering
pull/5965/head
Pavel Závora 2022-06-24 05:52:59 +02:00 committed by GitHub
commit 42e4b72025
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 27 additions and 8 deletions

View File

@ -78,8 +78,12 @@ export class Dropdown extends Component<Props, State> {
} }
public handleHighlight = (itemIndex: number) => () => { public handleHighlight = (itemIndex: number) => () => {
// setup highlighted element only in auto-complete mode,
// otherwise rely upon CSS :hover highlighting
if (this.props.useAutoComplete) {
this.setState({highlightedItemIndex: itemIndex}) this.setState({highlightedItemIndex: itemIndex})
} }
}
public toggleMenu = (e?: MouseEvent<HTMLDivElement>) => { public toggleMenu = (e?: MouseEvent<HTMLDivElement>) => {
if (e) { if (e) {
@ -158,6 +162,10 @@ export class Dropdown extends Component<Props, State> {
}) })
} }
private setDropdownRef = (ref: any) => {
this.dropdownRef = ref
}
public render() { public render() {
const { const {
items, items,
@ -188,7 +196,7 @@ export class Dropdown extends Component<Props, State> {
[className]: className, [className]: className,
})} })}
tabIndex={tabIndex} tabIndex={tabIndex}
ref={r => (this.dropdownRef = r)} ref={this.setDropdownRef}
data-test="dropdown-toggle" data-test="dropdown-toggle"
> >
{useAutoComplete && isOpen ? ( {useAutoComplete && isOpen ? (

View File

@ -108,7 +108,11 @@ const DropdownMenu: FunctionComponent<Props> = ({
autoHeight={true} autoHeight={true}
maxHeight={DROPDOWN_MENU_MAX_HEIGHT} maxHeight={DROPDOWN_MENU_MAX_HEIGHT}
> >
{menuLabel ? <li className="dropdown-header">{menuLabel}</li> : null} {menuLabel ? (
<li className="dropdown-header" key="header">
{menuLabel}
</li>
) : null}
{items.map((item, i) => ( {items.map((item, i) => (
<DropdownMenuItem <DropdownMenuItem
item={item} item={item}

View File

@ -1,4 +1,4 @@
import React, {FunctionComponent, MouseEvent} from 'react' import React, {MouseEvent, useCallback} from 'react'
import _ from 'lodash' import _ from 'lodash'
import classnames from 'classnames' import classnames from 'classnames'
@ -28,7 +28,7 @@ interface ItemProps {
onAction?: OnActionHandler onAction?: OnActionHandler
} }
const DropdownMenuItem: FunctionComponent<ItemProps> = ({ const DropdownMenuItem = ({
item, item,
highlightedItemIndex, highlightedItemIndex,
onSelection, onSelection,
@ -37,7 +37,7 @@ const DropdownMenuItem: FunctionComponent<ItemProps> = ({
onAction, onAction,
selected, selected,
index, index,
}) => { }: ItemProps) => {
if (_.isString(item)) { if (_.isString(item)) {
item = {text: item} item = {text: item}
} }
@ -46,6 +46,14 @@ const DropdownMenuItem: FunctionComponent<ItemProps> = ({
return <li className="dropdown-divider" /> return <li className="dropdown-divider" />
} }
const onClick = useCallback(
(e: MouseEvent<HTMLAnchorElement>) => {
e.preventDefault()
onSelection(item)(e)
},
[item]
)
return ( return (
<li <li
className={classnames('dropdown-item', { className={classnames('dropdown-item', {
@ -54,7 +62,7 @@ const DropdownMenuItem: FunctionComponent<ItemProps> = ({
})} })}
data-test={`${item.text}-dropdown-item`} data-test={`${item.text}-dropdown-item`}
> >
<a href="#" onClick={onSelection(item)} onMouseOver={onHighlight(index)}> <a href="#" onClick={onClick} onMouseOver={onHighlight(index)}>
{item.text} {item.text}
</a> </a>
{actions && !!actions.length && ( {actions && !!actions.length && (

View File

@ -69,7 +69,6 @@ $dropdown-purple-header: $c-potassium;
&-340 .dropdown-toggle {width: 340px;} &-340 .dropdown-toggle {width: 340px;}
} }
.dropdown:focus,
.dropdown.open, .dropdown.open,
.dropdown.open:focus { .dropdown.open:focus {
outline: none; outline: none;