Пользовательский компонент автозаполнения, не отображающий вывод при первом поиске - PullRequest
1 голос
/ 11 мая 2019

Я создал свой собственный компонент автозаполнения (Autosuggestions). Все работает нормально, когда я передаю жестко запрограммированный массив строк компоненту автозаполнения, но когда я пытаюсь передать данные из API в качестве реквизита, при первом поиске ничего не отображается. Результаты показывают каждый раз точно после первого раза

Я пробовал разные варианты, но похоже, что когда пользователь ищет в первый раз, данных там нет, а автозаполнение отображается с пустым массивом. Я протестировал одну и ту же конечную точку API, и она возвращает данные так, как и должна при каждом поиске.

Домашний компонент, который содержит автозаполнение

        const filteredUsers = this.props.searchUsers.map((item) => item.firstName).filter((item) => item !== null);

        const autocomplete = (
            <AutoComplete
                items={filteredUsers}
                placeholder="Search..."
                label="Search"
                onTextChanged={this.searchUsers}
                fieldName="Search"
                formName="autocomplete"
            />
        );

Компонент автозаполнения, который фильтрует вставленные данные и показывает список предложений. Возможно, проблема в onTextChange:

export class AutoComplete extends Component {
    constructor(props) {
        super(props);
        this.state = {
            suggestions: [],
            text: '',
        };
    }

    // Matching and filtering suggestions fetched from the backend and text that user has entered
    onTextChanged = (e) => {
        const value = e.target.value;
        let suggestions = [];
        if (value.length > 0) {
            this.props.onTextChanged(value);
            const regex = new RegExp(`^${value}`, 'i');
            suggestions = this.props.items.sort().filter((v) => regex.test(v));
        }
        this.setState({ suggestions, text: value });
    };

    // Update state each time user press suggestion
    suggestionSelected = (value) => {
        this.setState(() => ({
            text: value,
            suggestions: []
        }));
    };

    // User pressed the enter key
    onPressEnter = (e) => {
        if (e.keyCode === 13) {
            this.props.onPressEnter(this.state.text);
        }
    };

    render() {
        const { text } = this.state;
        return (
            <div style={styles.autocompleteContainerStyles}>
                <Field
                    label={this.props.placeholder}
                    onKeyDown={this.onPressEnter}
                    onFocus={this.props.onFocus}
                    name={this.props.fieldName}
                    formValue={text}
                    onChange={this.onTextChanged}
                    component={RenderAutocompleteField}
                    type="text"
                />
                <Suggestions
                    suggestions={this.state.suggestions}
                    suggestionSelected={this.suggestionSelected}
                    theme="default"
                />
            </div>
        );
    }
}

const styles = {
    autocompleteContainerStyles: {
        position: 'relative',
        display: 'inline',
        width: '100%'
    }
};

AutoComplete.propTypes = {
    items:  PropTypes.array.isRequired,
    placeholder: PropTypes.string.isRequired,
    onTextChanged: PropTypes.func.isRequired,
    fieldName: PropTypes.string.isRequired,
    label: PropTypes.string.isRequired,
    onPressEnter: PropTypes.func.isRequired,
    onFocus: PropTypes.func
};

export default reduxForm({
    form: 'Autocomplete'
})(AutoComplete);

Ожидаемые результаты: каждый раз, когда пользователь использует textinput для поиска, он должен получать результаты предложений Фактические результаты: пользователь, впервые использующий textinput для поиска, не получает данных. Только после первого поступления данных

1 Ответ

1 голос
/ 11 мая 2019

Он работает, когда он жестко задан, но не при использовании вашего API, потому что ваша фильтрация происходит в onTextChanged.Когда он жестко задан, у вашего AutoComplete есть значение для работы при первом вызове onTextChanged (this.props.items.sort().filter(...), но с API ваша items опора будет пустой до тех пор, пока вы не вернете API - после выполнения этой функции.

Чтобы обработать результаты вашего API, вам потребуется выполнить фильтрацию при смене реквизита.Реакционные документы на самом деле охватывают очень похожий случай здесь (см. Второй пример, поскольку первый показывает, как использование getDerivedStateFromProps излишне сложно), важной частью является то, что они используют PureComponent, чтобы избежать ненужных повторов.-рендеринга и затем выполнить фильтрацию в рендере, например, в вашем случае:

render() {
  // Derive your filtered suggestions from your props in render - this way when your API updates your items prop, it will re-render with the new data
  const { text } = this.state;
  const regex = new RegExp(`^${text}`, 'i');
  suggestions = this.props.items.sort().filter((v) => regex.test(v));

  ...
  <Suggestions
    suggestions={suggestions}
    ...
  />
  ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...