I have:
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
})
}
The problem is, is that it seems the setState after the action fires immediately, thus not giving me the effect in another component.
How can I setState only after the action has completed (regardless of success or fail)?
Here is my action:
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;
Update:
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
})
}
You are using an
updating
state, that shows your process is asynchronous. The code you are dispatching is indeed a promise, and dispatching an action when the process is done :'RECEIVED_JOBS_DATA'
.You should hence move the
updatingField
to be a component prop that comes from the store, and is changed in your reducer whenever the action starts and ends.That way, you could just use
this.props.updatingField
in your component, which value will come from the store and depend on the current state of your external request.That way, you'll follow one React/Flux best practice of preferring global state instead of local state.