Реагировать на узкое место ввода ввода текста - PullRequest
1 голос
/ 30 июня 2019

У меня есть большое приложение реагирования (с Redux), которое имеет огромное узкое место.

Мы осуществили поиск продукта, используя номер продукта или название продукта, и этот поиск чрезвычайно запаздывает.

Проблема: если пользователь вводит некоторые символы, эти символы отображаются в InputField действительно с задержкой.Пользовательский интерфейс заморожен на пару секунд.В Internet Explorer 11 поиск практически недоступен.

Это TextField с пользовательским интерфейсом материала, который фильтрует продукты.

Что я уже сделал для оптимизации:

  1. Заменены такие вещи, как style = {{maxHeight: 230, overflowY: 'scroll',}} с const cssStyle = {..}
  2. Изменены некоторые критические компонентыс React.Component до React.PureComponent
  3. Добавлено shouldComponentUpdate для нашего SearchComponent
  4. Удалено некоторое ненужное закрытиеbindings
  5. Удалено несколько ненужных объектов
  6. Удалено все console.log ()
  7. Добавлено 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>

Кажется, я не нашел проблему с производительностью, поскольку она все еще существует.Может кто-нибудь помочь здесь?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...