A skeleton that keeps the layout still
Three rows of 48 px plus 8 px gaps, in both states. Press Run again to watch the grey rows turn into people without anything moving.
Every request can be loading, failed, empty or successful, so model it with one status value, design a screen for each state (skeletons, retry buttons, empty messages, optimistic hints), and keep the layout from jumping when data arrives.
Change the code and press Run (Ctrl+Enter). Predict what will happen first, then break it on purpose and read what changes. Your edits are saved and match the lesson page.
Ready for more? This phase has 6 hands-on exercises with automatic checks.
Practice questions
Write the code in the editor, run it, then open the model answer to compare.
Write a useFetch(fn, deps) hook that returns { status, data, error, retry } using one state object and the ignore flag.
Write a ProductList that shows a skeleton of 4 cards while loading, an empty state when the array is empty, and the products otherwise.
Add an optimistic "like" button: the count goes up at once, and goes back down with an error message if fakeLike() rejects.
Explain it without notes
Why model a request with one status value instead of separate booleans?
What is layout shift, why does it matter, and how do skeletons help?
How would you implement a retry button for data fetched in an effect?
Explain an optimistic update and what must happen when the server rejects it.
Preview
Console
Nothing logged yet.Expected console output
list height while loading: 160 px
list height when loaded: 160 px