0
0
NextJSframework~20 mins

Optimistic state updates in NextJS - Practice Problems & Coding Challenges

Choose your learning style9 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.