Reputation: 1321
So I have an app I'm working on with React/Redux. It involves autosaving an entity to a datastore via api as values are changed.
I want to present the user with a "loading" indicator while the entity is being saved and then indicate "Saved!" or some other message once the response comes back from the api and updates the entity's state.
I actually have this working just fine. My reducers are
case "UPDATE_ROUND_REQUEST":
newState = {...state};
newState[action.meta.id].isSaving = true;
return newState;
case "UPDATE_ROUND":
newState = {...state};
newState[action.meta.id] = action.payload; // This response doesn't have the isSaving prop set
return newState;
And my component props receive this entity and the component accesses the isSaving
property to display the "saving" message I want
The only problem is that my api returns data in something like 50ms. Basically instant, instant enough that this message is never seen. From a UX perspective what I would like is for my component, when it detects via props that the entity is in the process of loading, to display the saving message for a reasonable period of time so that the user is confident that the data is saved.
I'm struggling with handling that in some sort of stateless way.
Any tips appreciated!
Upvotes: 1
Views: 354
Reputation: 5450
I would love to hear other answers on this because it's something I think about as well. Here is one solution that I believe can work. There may be a more performant solution out there though, and it might not be preferable to delay the response from a reducer artificially like I do in my example.
The code below is untested but I believe conceptually it will work.
import moment from 'moment';
const round = (
state = [],
action,
) => {
switch (action.type) {
case "UPDATE_ROUND_REQUEST":
const newState = {...state};
newState[action.meta.id].isSaving= true;
newState[action.meta.id].requestTime= moment(new Date());
return newState;
case "UPDATE_ROUND":
// get difference between now and when the request was sent.
const difference = moment(new Date).diff(state[action.meta.id].requestTime);
const newState = {...state};
// reset isSaving to false, and changes requestTime back null (default)
newState[action.meta.id] = {...action.payload, isSaving: false, requestTime: null};
// if difference is greater than 3 seconds, return the new state immediately.
if (difference > 3000) {
// return new state with updated data for the value at newState[action.meta.id].
return newState;
}
// else, if the difference is less than 3 seconds (3000ms), wait the difference and then return the new state
setTimeout(() => {
return newState;
}, 3000 - difference);
default: return state;
}
};
Upvotes: 1