reactjsasynchronousreactjs-fluxoptimistic-ui

Optimistic Updates Using Flux (async)


I am trying to add optimistic updates to my Flux model. I am smushing the UI action dispatch and the server action dispatch into one action. My code in the action creator looks like this:

deleteItem: function(itemId) {

    // optimistic update
    WebshipDispatcher.handleServerAction({
        type: ActionTypes.DELETE_ITEM,
        deleteStatus: 'success',
        itemId: itemId
    });

    // now let's actually check if that was the correct result
    AppAjaxUtil.get('/deleteItem', {itemId: itemId}, function(result) {

        WebshipDispatcher.handleServerAction({
            type: ActionTypes.DELETE_ITEM,
            deleteStatus: result.status, // 'success' or 'failure'
            itemId: itemId
        });

    }, function(error) {

        WebshipDispatcher.handleServerAction({
            type: ActionTypes.DELETE_ITEM,
            error: error
        });

    });
}

Is this an appropriate way to allow for optimistic updates or am I thinking about this piece incorrectly?


Solution

  • @fisherwebdev is right. The true logic would happen in your store. For example how would you handle the logic when an item does fail to delete? That becomes a beast on it's own. You don't really want to remove the item from your store unless you have confirmation from the server. A library like Ext marks the record as dirty while it waits for a successful response from the server. So the update is still happening optimistically, but the user and the record are notified if the server fails.

    So you could have a collection of dirty records in your store that are removed when your server responds with success. This is rough, but something like the following:

    deleteItem: function(itemId) {
    
        // optimistic update
        WebshipDispatcher.handleServerAction({
            type: ActionTypes.MARK_ITEM_AS_DIRTY,
            deleteStatus: 'success',
            itemId: itemId
        });
    
        // now let's actually check if that was the correct result
        AppAjaxUtil.get('/deleteItem', {itemId: itemId}, function(result) {
    
            WebshipDispatcher.handleServerAction({
                type: result.status ? ActionTypes.DELETE_ITEM : ActionTypes.DELETE_ITEM_FAIL,
                deleteStatus: result.status, // 'success' or 'failure'
                itemId: itemId
            });
    
        }, function(error) {
    
            WebshipDispatcher.handleServerAction({
                type: ActionTypes.DELETE_ITEM_FAIL,
                error: error,
                itemId: itemId
            });
    
        });
    }
    

    So basically you remove the dirty record from your store if you your response is successful. Otherwise you have a reference of your dirty records in your store that can try again with your server behind the scenes while your app is still running. So in essence your user does not have to sit and wait for a response.