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, предпочитая глобальное состояние вместо локального.