ReactJS Делайте что-то только после завершения действия

Я имею:

onKeyPress(id, e) {
        if(e.key == 'Enter') {
            this.saveField(id, e.target.value);
        }
    }

    onBlur(id, e) {
        this.saveField(id, e.target.value);
    }

    saveField(id, date) {
        this.setState({
            updatingField: true
        })
        this.context.executeAction(SetJobChaserDate, {date: date, id: id});
        this.setState({
            editingChaser: false,
            editingTrackingSent: false,
            updatingField: false
        })
    }

Проблема в том, что, похоже, что setState после действия запускается немедленно, что не дает мне эффекта в другом компоненте.

Как мне установить setState только после того, как действие завершено (независимо от того, успешен он или нет)?


Вот мое действие:

import qwest from 'qwest';

export default function SetJobChaserDate(actionContext, payload) {
    return qwest.post('jobs/set/chaser-date', {id: payload.id, date: payload.date}, {responseType: 'json'})
        .then(function (response) {

            actionContext.dispatch('RECEIVED_JOBS_DATA', {data: response.response, clear: false})

        })
}

import { EventEmitter } from 'events';

class JobStore extends EventEmitter {

    constructor() {
        super();
        this.jobs = new Map();
        this.counts = {};
        this.loading = false;
    }

    handleJobsData(payload) {
        if (payload.clear === true) {
            this.jobs = new Map();
        }
        payload.data.jobs.forEach((job) => {
            this.jobs.set(job.id, job);
        });
        if(payload.data.counts) {
            this.counts = payload.data.counts;
        }
        this.loading = false;
        this.emit('change');

    }

    handleReceiving() {
        this.loading = true;
        this.emit('loading');
    }

    handleCounts(payload) {
        console.log(payload)
    }

    getCounts() {
        return this.counts;
    }

    getJobs() {
        return this.jobs;
    }

    dehydrate () {
        return this.jobs;
    }

    rehydrate (state) {

    }

}

JobStore.dispatchToken = null;

JobStore.handlers = {
    'RECEIVED_JOBS_DATA': 'handleJobsData',
    'RECEIVED_COUNTS'   : 'handleCounts',
    'RECEIVING_JOB_DATA': 'handleReceiving'
};

JobStore.storeName = 'JobStore';

export default JobStore;

Обновить:

componentWillReceiveProps() {
        this.context.getStore(JobStore).on('change', () => {
            this.setState({
                updatingField: false
            });
        });
    }

    onKeyPress(id, e) {
        if (e.key == 'Enter') {
            this.saveField(id, e.target.value);
        }
    }

    onBlur(id, e) {
        this.saveField(id, e.target);
    }

    saveField(id, target) {
        console.log(target)
        this.setState({
            updatingField: true
        })
        this.context.executeAction(SetJobChaserDate, {date: target.value, id: id});
        this.setState({
            editingChaser: false,
            editingTrackingSent: false
        })
    }

1 ответ

Вы используете updating состояние, которое показывает, что ваш процесс асинхронный. Код, который вы отправляете, действительно является обещанием и отправляет действие, когда процесс завершен: 'RECEIVED_JOBS_DATA',

Вы должны, следовательно, переместить updatingField быть составной опорой, которая поступает из магазина и изменяется в вашем редукторе всякий раз, когда действие начинается и заканчивается.

Таким образом, вы можете просто использовать this.props.updatingField в вашем компоненте, значение которого поступит из магазина и зависит от текущего состояния вашего внешнего запроса.

Таким образом, вы будете следовать одной из лучших практик React/Flux, предпочитая глобальное состояние вместо локального.

Другие вопросы по тегам