0
0
NextJSframework~5 mins

Optimistic state updates in NextJS

Choose your learning style9 modes available
Introduction

Optimistic state updates make your app feel faster by showing changes right away before the server confirms them.

When you want to update a list item immediately after a user action, like liking a post.
When submitting a form and you want to show the new data instantly without waiting for the server.
When toggling a switch or button and you want the UI to respond instantly.
When you want to improve user experience by reducing waiting time after an action.
Syntax
NextJS
const [data, setData] = useState(initialData);

async function updateData(newValue) {
  const previousData = data;
  // Update UI immediately
  setData(newValue);

  try {
    // Send update to server
    await fetch('/api/update', { method: 'POST', body: JSON.stringify(newValue), headers: { 'Content-Type': 'application/json' } });
  } catch (error) {
    // Revert UI if server update fails
    setData(previousData);
  }
}

Use setState to update UI before server response.

Handle errors to revert changes if server update fails.

Examples
Increment count optimistically without waiting for server.
NextJS
const [count, setCount] = useState(0);

function increment() {
  setCount((prev) => prev + 1); // Update UI immediately
  fetch('/api/increment', { method: 'POST' });
}
Add an item to list optimistically and revert on error.
NextJS
const [items, setItems] = useState(['apple', 'banana']);

async function addItem(item) {
  setItems([...items, item]); // Show new item right away
  try {
    await fetch('/api/add', { method: 'POST', body: JSON.stringify({ item }), headers: { 'Content-Type': 'application/json' } });
  } catch {
    setItems(items); // Revert if error
  }
}
Sample Program

This component lets users like or unlike something. It updates the button immediately when clicked. If the server update fails, it changes back and shows an error message.

NextJS
import React, { useState } from 'react';

export default function LikeButton() {
  const [liked, setLiked] = useState(false);
  const [error, setError] = useState(null);

  async function toggleLike() {
    const previousLiked = liked;
    setLiked(!liked); // Optimistic update
    setError(null);

    try {
      const response = await fetch('/api/like', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ liked: !liked })
      });
      if (!response.ok) throw new Error('Server error');
    } catch (e) {
      setLiked(previousLiked); // Revert on error
      setError('Failed to update like status');
    }
  }

  return (
    <div>
      <button aria-pressed={liked} onClick={toggleLike} aria-label="Like button">
        {liked ? '❤️ Liked' : '🤍 Like'}
      </button>
      {error && <p role="alert" style={{ color: 'red' }}>{error}</p>}
    </div>
  );
}
OutputSuccess
Important Notes

Always handle errors to keep UI and server data in sync.

Optimistic updates improve user experience but need careful rollback logic.

Use ARIA attributes like aria-pressed for accessibility on toggle buttons.

Summary

Optimistic updates show changes instantly before server confirms.

They make apps feel faster and more responsive.

Always plan to revert changes if server update fails.