Going through the Optimistic UI approach in pure React apps and Apollo Graphql
As front-end engineers, we want to provide the most reliable and comprehensive user interface by using many techniques, new technologies, frameworks or just our knowledge and experience. Everything just to achieve a better user experience and ensuring a clear and meaningful interface for the end user of our application.
Nowadays, one well-known technique that could improve our apps, is the Optimistic UI. This is a very simple solution to avoid some part of the loading states during the updates and pretending that some long time actions are called immediately. Sounds a bit weird, I know, but practically, it’s not a breakthrough — just straightforward technique.
Starting from scratch, just try to imagine, a very simple application that is doing something in the background asynchronously, let’s say… some request API call (for sure the most common). For instance, it could be a simple button which generates API call for every single click, such as Like button.
👍 The UX of the Like button
When we click the like button for sure it changes the state of our application, not only in the front-end app but also in backend side — that state must be saved. Without question, some API calls must be triggered and that means we have to wait for the response, it’s inevitable.
Above diagram presents that situation. We are clicking the button, but as an end user, we don’t know if it works. There is no reaction. Only what we can see is increasing the number of likes after some delay — the final result. That delay, of course, comes from API calls and when it finished, the likes pointer is growing.
A user is not aware of what is happening. Let’s try to solve that problem by introducing some reaction on click— displaying the loading state (I’m pretty sure you have been doing this).
Now when we click on the like button, the loading state appears until API call is finished. After API call, the number of likes goes up and end user can notice that something happened, it wasn’t a dead-click without reaction.
Now the new question arises — are we able to avoid that delay caused by API calls and increase the number of likes at the same time, immediately? The first answer that comes to our mind is definitely not, because we are changing the state of the application and that fact has to be saved, but… this is a point where Optimistic UI has something to say.
First of all, the actual thing what we do is just synchronization our front-end state with the state in the backend, so we can update our state as first and the API calls could be pending in the background. In the case when something went wrong with some call, we can reject our changes. That’s exactly how it works.
As you can see, now when we click “Like”, the changes are applying instantly. As a user, we see that action has just happened, but actually not, not yet. It’s waiting for backend save, but meanwhile, a user doesn’t see this — from his perspective, he has already “liked” something and can move forward.
⚡️Optimistic Todo list
Now we know what the Optimistic UI actually is, so we are ready to use it in the real app. A classic example is, of course, the todo list. This app will be super easy. Only thing what we want to do is just add a new element to the list where mentioned element is the value of the input field. Furthermore, information about adding that element has to be sent to the backend, but this case we’ll simulate it by the code (look at the source in the examples). In order to compare two approaches — let’s try to build two version of this list.
The first one is the todo list with the loading state. We have to wait for adding a new item to the list (until the request is finished), so we have to add the information about what is happening (saving… text in the button). The implementation is here:
[full demo link: DEMO]
Now, based on the existing code of loading state approach, we can change it to achieve the optimistic way. What is the algorithm of it?
Firstly, we have to assume the positive scenario and predict the results from the API. That predicted results we’ll show to the user, but they have to be unequivocal and recognizable in the code because we want to display them in a different way than rest (eg. darker or brighter color). How we can do this? For instance, by using some flag or the negative ID (when ID is positive, it means real one, otherwise — predicted)
As next, we have to send the request to the API. When it’s finished, replace the fake one (predicted) by the element comes from API. If some errors arise, we need to rollback our predicted stuff. Look at the code below:
[full demo link: DEMO]
🚀 Using Apollo
The developers who are using GraphQL and Apollo stuff should be grateful of that convenient library. In terms of optimistic UI, we have to use just one config field to achieve the same outcome. Only what we need to do, is set the optimisticResponse field in mutate() function. It determines how the response would look like (predicted response ) — exactly the same thing what we have done before.
[full demo link: DEMO]
That’s it! Everything is clear? It’s simple, isn’t it? 😃