React (16.4.1) setState() обновляет состояние на одно событие onChange за текущим событием onChange с помощью компонента act-select

У меня есть 2 компонента реакции-выбора, и я хочу установить следующее: когда пользователь делает выбор из обоих выбранных компонентов (порядок не имеет значения), то запускается ajax для получения данных с сервера. Выбор из обоих этих компонентов необходим для полного заполнения параметров GET для вызова ajax.

У меня есть эти 2 обработчика для события onChange в элементах реагировать на выбор:

filterSiteSelect(selection) {
    const siteId = selection.id;
    const siteName = selection.name;

    this.setState({
        siteId, siteName
    }, this.getTableData());
}

filterLineTypeSelect(selection) {
    const lineTypeId = selection.id;
    const lineTypeName = selection.name;

    this.setState({
        lineTypeId, lineTypeName
    }, this.getTableData());
}

И мой метод getTableData() выглядит так:

getTableData() {
    const {
        productId, siteId, lineTypeId, stages, tableUrl
    } = this.state;

// tableUrl = `p=field&t=view&gapi=1&product_id=${productId}&site_id=${siteId}&line_type_id=${lineTypeId}&stage_ids=${stages}`

    if (productId && siteId && lineTypeId && !_.isEmpty(stages)) {
        Axios.get(tableUrl)
            .then((result) => {
                this.setState({
                    rawData: { ...result.data.data }
                });
            });
    }
}

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

Я также пытался использовать ComponentDidUpdate() для вызова AJAX с этим кодом (я удалил getTable() данные от каждого из setState() звонки, когда я изменился на componentDidUpdate(prevState)):

componentDidUpdate(prevState) {
    const {
        siteId, lineTypeId, stages
    } = this.state;

    if (lineTypeId !== prevState.lineTypeId && siteId !== prevState.siteId && !_.isEqual(stages, prevState.stages)) {
        this.getTableData();
    }
}

Но что происходит при использовании componentDidUpdate() Метод жизненного цикла он запускает Ajax снова и снова, никогда не останавливаясь, и я считаю, что это потому, что setState() никогда не обновляет состояние последнего выбранного компонента, с которым взаимодействовал пользователь.

Так что я думаю, что я делаю что-то не так в своем использовании / понимании setState() метод (или проблема заключается в компоненте act-select...).

Любая идея, помощь или обсуждение того, чего я пытаюсь достичь, будет принята с благодарностью!

2 ответа

Решение

Когда вы передаете второй аргумент setState()например, setState({foo: bar}, <something>), <something> должна быть функцией обратного вызова, которая вызывается, когда setState() закончил обновление. В вашем коде вместо передачи вашей функции this.getTableData в качестве аргумента вы передаете выражение, возвращаемое из вызова this.getTableData(), в этом случае undefined,

В вашем коде здесь:

filterSiteSelect(selection) {
    const siteId = selection.id;
    const siteName = selection.name;

    this.setState({
        siteId, siteName
    }, this.getTableData());
}

filterLineTypeSelect(selection) {
    const lineTypeId = selection.id;
    const lineTypeName = selection.name;

    this.setState({
        lineTypeId, lineTypeName
    }, this.getTableData());
}

Когда вы синхронно звоните setState() и добавить обновление состояния в очередь, вы также синхронно звоните this.getTableData() который запускается немедленно, проверяет некоторые логические переменные в ваших переменных состояния, может пытаться выполнить ajax-вызов и т. д.

Попробуйте просто удалить () так что вы передаете функцию непосредственно в setState в качестве аргумента вместо случайного вызова функции.:)

filterSiteSelect(selection) {
    const siteId = selection.id;
    const siteName = selection.name;

    this.setState({
        siteId, siteName
    }, this.getTableData);
}

filterLineTypeSelect(selection) {
    const lineTypeId = selection.id;
    const lineTypeName = selection.name;

    this.setState({
        lineTypeId, lineTypeName
    }, this.getTableData);
}

setState Второй параметр - это обратный вызов. Это означает, что вы должны передавать ссылку на вызываемую функцию вместо вызова самой функции.

this.setState({
    siteId, siteName
}, this.getTableData());

Должно быть

this.setState({
    siteId, siteName
}, this.getTableData);
Другие вопросы по тегам