Optimising User Experience: Moving Beyond Loading States

Feb 28, 2025

Amal

Improving UX with Optimistic Updates in React

Loading states are often a necessary evil in web applications, but they don’t always provide the best user experience. Users expect certain actions to take time — like fetching a dashboard of analytics — but interactions such as clicking a like button, toggling between settings, or marking a notification as read should feel instantaneous. Social media platforms have trained users to expect immediate feedback when they engage with content. If a delay occurs, even for a fraction of a second, it can feel unresponsive and frustrating.

This is where useOptimistic hook from React 19 come into play. Instead of waiting for the server response to confirm an action, we assume success and update the UI instantly. If the request fails, we gracefully revert the UI to its previous state.


A Practical Example in Action

Try It Yourself: Optimistic UI vs. Traditional State Management: https://codesandbox.io/p/github/vinuman/Use-optimisation-demo/main

import { useOptimistic, useState, useTransition } from "react";
import { getStyle } from "./utils";

export function LikeButton() {
  const [liked, setLiked] = useState(false);
  const [isPending, startTransition] = useTransition();

  const [optimisticLiked, toggleOptimisticLike] = useOptimistic(
    liked,
    (currentLiked) => !currentLiked
  );

  async function handleLike() {
    if (isPending) return;
    toggleOptimisticLike(); // Instantly update UI

    startTransition(async () => {
      try {
        await new Promise((resolve) => setTimeout(resolve, 1000)); // Simulate API call
        setLiked((prev) => !prev); // Confirm state change
      } catch (error) {
        console.error("Like action failed", error);
        setLiked((prev) => prev); // Revert if mutation fails
      }
    });
  }

  const style = getStyle(optimisticLiked);

  return (
    <div>
      <p style={{ fontSize: "24px" }}>Optimised</p>
      <button style={style} onClick={handleLike}>
        {optimisticLiked ? "Liked" : "Like"}
      </button>
    </div>
  );
}

By wrapping our asynchronous operation inside startTransition(a topic for later), we are instructing React that this update is a non-urgent state update. This allows React to prioritize more important updates (such as user interactions) while deferring non-essential rendering. In the case of our LikeButton, React ensures that the UI remains responsive even if the mutation takes longer to resolve.


Navigating Errors and Pending States in Optimistic Updates

While useOptimistic enhances perceived performance, it does not eliminate the need for careful error handling. Some key considerations include:

  1. Error Reversion — If the async operation fails, we need to handle rolling back the optimistic update. We might need to be smart about implementing a more structured rollback mechanism.

  2. Pending State Awareness — While useOptimistic allows the UI to update instantly, the mutation still takes time to process. We still need to track whether the operation is pending (isPending) so that we can provide appropriate visual feedback, such as disabling the button. This is where a frontend engineer’s expertise comes into play, ensuring a seamless and intuitive user experience.

  3. Ensuring Idempotency — When using optimistic updates, our backend operations should ideally be idempotent. This means that if a request is retried due to a temporary failure, it should not result in incorrect state changes.


Conclusion

The introduction of useOptimistic is a step toward making UI updates feel more natural and intuitive. Developers still need to balance speed with correctness, ensuring that fallback mechanisms are in place to handle failures gracefully.

This hook is best suited for interactions where users expect instant feedback. Some common use cases include:

  • Liking and bookmarking content

  • Adding or removing items from a list

  • Toggling UI preferences

However, for more complex CRUD operations where data consistency is critical (such as payments or sensitive actions), a more traditional approach with explicit loading and error handling may be necessary.

Contact Us

Contact Us

Contact Us

Connect with Us

Get in Touch with Us

Get in Touch with Us

Let us transform your ideas into impactful solutions by combining AI, design, and technology

Work with us

Bring Ideas to Life with Pentagon Studio

Bring Ideas to Life with Pentagon Studio

We are a team of passionate developers, designers, and researchers dedicated to building the future together.

We are a team of passionate developers, designers, and researchers dedicated to building the future together.

98%

Client satisfaction in project outcomes

20+ Projects done

Including web design, app development, and Branding

10+ Clients

Across industries and regions

10+

We are a team of passionate developers, designers, and researchers dedicated to building the future together.

We are a team of passionate developers, designers, and researchers dedicated to building the future together.

We are a team of passionate developers, designers, and researchers dedicated to building the future together.

We are a team of passionate developers, designers, and researchers dedicated to building the future together.

Made with ❤️ All rights reserved by Pentagon Studio.

Made with ❤️ All rights reserved by Pentagon Studio.

Made with ❤️ All rights reserved by Pentagon Studio.

Made with ❤️ All rights reserved by Pentagon Studio.