Bird
Raised Fist0
NextJSframework~20 mins

Optimistic state updates in NextJS - Practice Problems & Coding Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Optimistic Update Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ component_behavior
intermediate
2:00remaining
What happens immediately after clicking the button in this Next.js optimistic update?

Consider this Next.js component that updates a list of items optimistically when a button is clicked.

import { useState } from 'react';

export default function ItemList() {
  const [items, setItems] = useState(['apple', 'banana']);

  async function addItem() {
    setItems([...items, 'orange']); // optimistic update
    await fetch('/api/add', { method: 'POST', body: JSON.stringify({ item: 'orange' }) });
  }

  return (
    <div>
      <ul>
        {items.map(item => <li key={item}>{item}</li>)}
      </ul>
      <button onClick={addItem}>Add Orange</button>
    </div>
  );
}
NextJS
import { useState } from 'react';

export default function ItemList() {
  const [items, setItems] = useState(['apple', 'banana']);

  async function addItem() {
    setItems([...items, 'orange']); // optimistic update
    await fetch('/api/add', { method: 'POST', body: JSON.stringify({ item: 'orange' }) });
  }

  return (
    <div>
      <ul>
        {items.map(item => <li key={item}>{item}</li>)}
      </ul>
      <button onClick={addItem}>Add Orange</button>
    </div>
  );
}
AThe list removes 'banana' immediately after clicking the button.
BThe list waits for the server response before showing 'orange'.
CThe list immediately shows 'apple', 'banana', and 'orange' before the server responds.
DThe list clears all items immediately after clicking the button.
Attempts:
2 left
💡 Hint

Think about what 'optimistic update' means: updating UI before server confirms.

❓ state_output
intermediate
2:00remaining
What is the state of 'items' after a failed server call in this optimistic update?

In this Next.js component, the optimistic update adds 'grape' to the list, but the server call fails.

import { useState } from 'react';

export default function FruitList() {
  const [items, setItems] = useState(['apple', 'banana']);

  async function addGrape() {
    setItems([...items, 'grape']); // optimistic update
    try {
      const res = await fetch('/api/add-grape', { method: 'POST' });
      if (!res.ok) throw new Error('Failed');
    } catch {
      setItems(items); // rollback
    }
  }

  return (
    <div>
      <ul>
        {items.map(item => <li key={item}>{item}</li>)}
      </ul>
      <button onClick={addGrape}>Add Grape</button>
    </div>
  );
}
NextJS
import { useState } from 'react';

export default function FruitList() {
  const [items, setItems] = useState(['apple', 'banana']);

  async function addGrape() {
    setItems([...items, 'grape']); // optimistic update
    try {
      const res = await fetch('/api/add-grape', { method: 'POST' });
      if (!res.ok) throw new Error('Failed');
    } catch {
      setItems(items); // rollback
    }
  }

  return (
    <div>
      <ul>
        {items.map(item => <li key={item}>{item}</li>)}
      </ul>
      <button onClick={addGrape}>Add Grape</button>
    </div>
  );
}
AThe list remains ['apple', 'banana', 'grape'] after failure.
BThe list reverts to ['apple', 'banana'] after failure.
CThe list contains only ['grape'] after failure.
DThe list becomes empty after failure.
Attempts:
2 left
💡 Hint

Rollback means undoing the optimistic change if the server call fails.

📝 Syntax
advanced
2:00remaining
Which option correctly implements an optimistic update with rollback in Next.js?

Choose the code snippet that correctly updates state optimistically and rolls back on error.

A
const prevItems = items;
setItems([...items, 'pear']);
try {
  await fetch('/api/add-pear', { method: 'POST' });
} catch {
  setItems(prevItems);
}
B
const prevItems = items;
try {
  setItems([...items, 'pear']);
  await fetch('/api/add-pear', { method: 'POST' });
} catch {
  setItems(prevItems);
}
C
setItems([...items, 'pear']);
try {
  await fetch('/api/add-pear', { method: 'POST' });
} catch {
  setItems([]);
}
D
setItems([...items, 'pear']);
try {
  await fetch('/api/add-pear', { method: 'POST' });
} catch {
  setItems([...items]);
}
Attempts:
2 left
💡 Hint

Remember to save the previous state before updating optimistically.

🔧 Debug
advanced
2:00remaining
Why does this optimistic update not rollback correctly on error?

Review this code snippet:

const [items, setItems] = useState(['apple']);

async function addItem() {
  setItems([...items, 'mango']);
  try {
    await fetch('/api/add-mango', { method: 'POST' });
  } catch {
    setItems(items);
  }
}

Why might the rollback fail to restore the original list?

NextJS
const [items, setItems] = useState(['apple']);

async function addItem() {
  setItems([...items, 'mango']);
  try {
    await fetch('/api/add-mango', { method: 'POST' });
  } catch {
    setItems(items);
  }
}
ABecause the state update is asynchronous and cannot be rolled back.
BBecause setItems cannot be called inside catch blocks.
CBecause 'items' in catch refers to the updated state, not the original before update.
DBecause fetch does not throw errors on HTTP failures by default.
Attempts:
2 left
💡 Hint

Consider the conditions under which fetch() rejects its promise.

🧠 Conceptual
expert
2:00remaining
Which statement best describes the main benefit of optimistic state updates in Next.js?

Choose the best explanation for why developers use optimistic updates in Next.js applications.

AThey improve user experience by showing UI changes immediately without waiting for server confirmation.
BThey guarantee data consistency by waiting for server response before updating UI.
CThey simplify code by removing the need for error handling in server requests.
DThey prevent any UI changes until the server confirms the update.
Attempts:
2 left
💡 Hint

Think about how users feel when UI updates instantly.

Practice

(1/5)
1. What is the main purpose of optimistic state updates in Next.js applications?
easy
A. To delay UI updates until the server responds
B. To prevent any UI changes until the user refreshes the page
C. To update the UI immediately before the server confirms the change
D. To disable user interactions during server requests

Solution

  1. Step 1: Understand optimistic updates concept

    Optimistic updates update the UI immediately to make the app feel faster.
  2. Step 2: Compare options with concept

    Only To update the UI immediately before the server confirms the change describes updating UI before server confirmation, matching optimistic updates.
  3. Final Answer:

    To update the UI immediately before the server confirms the change -> Option C
  4. Quick Check:

    Optimistic update = immediate UI change [OK]
Hint: Optimistic means acting before confirmation [OK]
Common Mistakes:
  • Thinking UI waits for server response
  • Confusing optimistic with pessimistic updates
  • Assuming UI disables interactions
2. Which of the following is the correct way to implement an optimistic update using React's useState in Next.js?
easy
A. Use setTimeout to delay state update by 2 seconds
B. Update state after server response inside then()
C. Do not update state at all until server confirms
D. Update state immediately before sending server request

Solution

  1. Step 1: Recall optimistic update timing

    Optimistic updates change state immediately before server response.
  2. Step 2: Match options to timing

    Update state immediately before sending server request updates state immediately before request, fitting optimistic update pattern.
  3. Final Answer:

    Update state immediately before sending server request -> Option D
  4. Quick Check:

    Immediate state update = optimistic update [OK]
Hint: Update state before server reply for optimism [OK]
Common Mistakes:
  • Waiting for server response before updating state
  • Delaying state update unnecessarily
  • Not updating state at all
3. Consider this Next.js React component snippet using optimistic updates:
const [count, setCount] = useState(0);

async function increment() {
  setCount(count + 1); // optimistic update
  try {
    await fetch('/api/increment', { method: 'POST' });
  } catch {
    setCount(count); // revert on failure
  }
}

What will be the displayed count if the server request fails?
medium
A. The count reverts to the original value before increment
B. The count becomes undefined
C. The count resets to 0 regardless
D. The count remains incremented by 1

Solution

  1. Step 1: Analyze optimistic update and revert logic

    Count increments immediately, but on fetch failure, count resets to original value.
  2. Step 2: Understand revert on failure

    The catch block sets count back to original, undoing optimistic increment.
  3. Final Answer:

    The count reverts to the original value before increment -> Option A
  4. Quick Check:

    Failed fetch triggers revert = original count [OK]
Hint: Revert state on error to original value [OK]
Common Mistakes:
  • Assuming optimistic update stays after failure
  • Thinking count resets to zero always
  • Ignoring catch block revert
4. Given this code snippet for optimistic updates in Next.js:
const [items, setItems] = useState([]);

async function addItem(newItem) {
  setItems([...items, newItem]);
  try {
    await fetch('/api/add', { method: 'POST', body: JSON.stringify(newItem) });
  } catch {
    // What is missing here?
  }
}

What is the best fix to handle errors properly?
medium
A. Remove the optimistic update and update only after fetch
B. Add code to revert items state to previous value in catch
C. Ignore errors since optimistic update is enough
D. Add a console.log in catch without state change

Solution

  1. Step 1: Identify missing error handling

    Optimistic update changes state immediately, but no revert on failure.
  2. Step 2: Add revert logic in catch block

    To keep UI consistent, revert items to previous state if fetch fails.
  3. Final Answer:

    Add code to revert items state to previous value in catch -> Option B
  4. Quick Check:

    Revert state on error = correct error handling [OK]
Hint: Revert state in catch to fix errors [OK]
Common Mistakes:
  • Not reverting state on failure
  • Removing optimistic update unnecessarily
  • Only logging errors without UI fix
5. You want to implement optimistic updates for a list of tasks in Next.js. The user can add a task, and the UI should update immediately. However, if the server rejects the addition, the UI must revert. Which approach correctly handles this scenario?
hard
A. Update the tasks state immediately, then on server failure, reset tasks to previous state saved before update
B. Wait for server confirmation before updating tasks state to avoid inconsistencies
C. Update tasks state immediately and do nothing on failure, assuming server will eventually succeed
D. Clear the tasks list on server failure to force user refresh

Solution

  1. Step 1: Understand optimistic update with revert

    Optimistic update means immediate UI change, but must revert on failure to keep UI correct.
  2. Step 2: Evaluate options for correct revert handling

    Update the tasks state immediately, then on server failure, reset tasks to previous state saved before update saves previous state and reverts on failure, matching best practice.
  3. Final Answer:

    Update the tasks state immediately, then on server failure, reset tasks to previous state saved before update -> Option A
  4. Quick Check:

    Optimistic update + revert = Update the tasks state immediately, then on server failure, reset tasks to previous state saved before update [OK]
Hint: Save old state to revert if server fails [OK]
Common Mistakes:
  • Not reverting UI on failure
  • Waiting for server before UI update
  • Clearing list unnecessarily on error
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard