Prevent Doubly Updating and Reverting State in React

Erik Aybar
InstructorErik Aybar
Share this video with your friends

Social Share Links

Send Tweet

Optimistic UI updates come with challenges that can vary for every use case. In our scenario of “liking a tweet”, one challenge that we face is preventing doubly updating and reverting state in the event of the user clicking “like” in rapid succession. In the case of a request failure our current solution results in the false impression that the tweet was successfully liked.

One solution that fits our use case is to simply raise and lower a boolean flag to indicate whether a like tweet request is pending or not and short circuit our onClickLike method to "do nothing" if a request is already pending. Since we don’t require this information in our render method or on component state, we can simplify this further by making use of a class instance property to store this value.

Instructor: [00:00] Our heart icons are optimistically updating so that when we click them, they visually immediately update. Only in the event of a failure does it revert after the request is failed. If we look a little deeper, we'll see that we have a use case where a bug will arise if we click this rapidly. Ultimately, both requests failed when you get the visual impression here that the tweet was successfully liked.

[00:27] If we follow the timeline of events, if I click this twice in rapid succession, the first time we clicked it we transitioned to liking the tweet, so that the second time we clicked it, when we came here we said, "Oh, this is already liked."

[00:43] We again updated it to toggle that, which transitioned us to not liking it. When this request failed, we reverted state, swapping back to the current liked status, which it was already liked from the first optimistic update. We need to introduce a way to prevent multiple or conflicting invocations.

[01:06] One simplified solution we can introduce is we can add an instance property on here. We'll call this, "like request pending." This is going to begin as false. We could add this into our component state. Since we don't need it in render, we can apply this as an instance property and keep things a little bit simpler.

[01:28] We want to introduce this before we update our state. Immediately after we click this, what we want to do is we want to check our flag here that we're going to be raising and lowering. Ask if this like request pending, what we're going to do is, we're going to return and short-circuit this whole thing. We will log out here request already pending. Now, we can raise our flag here by saying, this like request pending is true.

[01:57] Once this request is completed in either the success or failure case, we're going to lower the flag. We will add an additional then handler here. We will set that flag to false. Now, if we come in here and click any of these in rapid succession, we'll see that we click and update our state immediately and fire off a request. The second time we click it, the request is already pending so that we've done nothing.

[02:23] To look at our failure case, before we had the bug where we would doubly revert our state, giving the false impression that the tweet was successfully liked. Now, we've caught and prevented that.