У меня есть большое приложение реагирования (с Redux), которое имеет огромное узкое место.
Мы осуществили поиск продукта, используя номер продукта или название продукта, и этот поиск чрезвычайно запаздывает.
Проблема: если пользователь вводит некоторые символы, эти символы отображаются в InputField действительно с задержкой.Пользовательский интерфейс заморожен на пару секунд.В Internet Explorer 11 поиск практически недоступен.
Это TextField с пользовательским интерфейсом материала, который фильтрует продукты.
Что я уже сделал для оптимизации:
- Заменены такие вещи, как style = {{maxHeight: 230, overflowY: 'scroll',}} с const cssStyle = {..}
- Изменены некоторые критические компонентыс React.Component до React.PureComponent
- Добавлено shouldComponentUpdate для нашего SearchComponent
- Удалено некоторое ненужное закрытиеbindings
- Удалено несколько ненужных объектов
- Удалено все console.log ()
- Добавлено debouncing для поля ввода (что делает его еще хуже)
Вот так выглядит наш SearchComponent на данный момент:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Downshift from 'downshift';
import TextField from '@material-ui/core/TextField';
import MenuItem from '@material-ui/core/MenuItem';
import Paper from '@material-ui/core/Paper';
import IconTooltip from '../helper/icon-tooltip';
import { translate } from '../../utils/translations';
const propTypes = {
values: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
legend: PropTypes.string,
helpText: PropTypes.string,
onFilter: PropTypes.func.isRequired,
selected: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
isItemAvailable: PropTypes.func,
};
const defaultProps = {
legend: '',
helpText: '',
selected: '',
isItemAvailable: () => true,
};
const mapNullToDefault = selected =>
(selected === null || selected === undefined ? '' : selected);
const mapDefaultToNull = selected => (!selected.length ? null : selected);
class AutoSuggestField extends Component {
shouldComponentUpdate(nextProps) {
return this.props.selected !== nextProps.selected;
}
getLegendNode() {
const { legend, helpText } = this.props;
return (
<legend>
{legend}{' '}
{helpText && helpText.length > 0 ? (
<IconTooltip helpText={helpText} />
) : (
''
)}
</legend>
);
}
handleEvent(event) {
const { onFilter } = this.props;
const value = mapDefaultToNull(event.target.value);
onFilter(value);
}
handleOnSelect(itemId, item) {
const { onFilter } = this.props;
if (item) {
onFilter(item.label);
}
}
render() {
const { values, selected, isItemAvailable } = this.props;
const inputValue = mapNullToDefault(selected);
const paperCSSStyle = {
maxHeight: 230,
overflowY: 'scroll',
};
return (
<div>
<div>{this.getLegendNode()}</div>
<Downshift
inputValue={inputValue}
onSelect={(itemId) => {
const item = values.find(i => i.id === itemId);
this.handleOnSelect(itemId, item);
}}
>
{/* See children-function on https://github.com/downshift-js/downshift#children-function */}
{({
isOpen,
openMenu,
highlightedIndex,
getInputProps,
getMenuProps,
getItemProps,
ref,
}) => (
<div>
<TextField
className="searchFormInputField"
InputProps={{
inputRef: ref,
...getInputProps({
onFocus: () => openMenu(),
onChange: (event) => {
this.handleEvent(event);
},
}),
}}
fullWidth
value={inputValue}
placeholder={translate('filter.autosuggest.default')}
/>
<div {...getMenuProps()}>
{isOpen && values && values.length ? (
<React.Fragment>
<Paper style={paperCSSStyle}>
{values.map((suggestion, index) => {
const isHighlighted = highlightedIndex === index;
const isSelected = false;
return (
<MenuItem
{...getItemProps({ item: suggestion.id })}
key={suggestion.id}
selected={isSelected}
title={suggestion.label}
component="div"
disabled={!isItemAvailable(suggestion)}
style={{
fontWeight: isHighlighted ? 800 : 400,
}}
>
{suggestion.label}
</MenuItem>
);
})}
</Paper>
</React.Fragment>
) : (
''
)}
</div>
</div>
)}
</Downshift>
</div>
);
}
}
AutoSuggestField.propTypes = propTypes;
AutoSuggestField.defaultProps = defaultProps;
export default AutoSuggestField;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.5.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.5.0/umd/react-dom.production.min.js"></script>
Кажется, я не нашел проблему с производительностью, поскольку она все еще существует.Может кто-нибудь помочь здесь?