items alone cannot tell the full story
When state.items is empty, the application may still be loading, may have loaded zero records or may have failed. Add an explicit status.
Imagine seeing an empty shop shelf. You cannot know whether delivery is still coming, the delivery contained nothing or the truck failed to arrive. The list alone does not explain the situation. status supplies the missing meaning.
const state = {
items: [],
search: '',
topic: 'all',
availableOnly: false,
selectedId: null,
status: 'not-started',
error: null
};
Use a small, deliberate set of status values:
not-started -> loading -> ready
-> empty
-> error
not-started: loading has not started.loading: the application is waiting.ready: one or more items arrived.empty: loading succeeded but returned zero items.error: loading did not produce a usable result.
Show the transition in init
async function init() {
connectEvents();
state.status = 'loading';
render();
try {
state.items = await fetchResources();
state.status = state.items.length === 0 ? 'empty' : 'ready';
} catch (error) {
state.status = 'error';
state.error = error instanceof Error ? error.message : 'Unknown error';
}
render();
}
The first render shows loading immediately. The second render shows the outcome. An error remains distinct from a valid empty result.
Render each state deliberately
function render() {
renderStatus(state.status, state.error);
if (state.status === 'ready') {
renderResources(getVisibleItems());
} else {
renderResources([]);
}
}
You may decide to keep old items visible during a refresh, but make that product decision explicit. Do not let accidental stale content communicate success.
Debug data loading with evidence
Use browser developer tools in this order:
- Network: Was a request sent to the intended URL?
- Status: Was the response 200, 404, 500 or another value?
- Response: Is the body valid JSON with the expected shape?
- Console: Did parsing, validation or rendering throw an error?
- State: After awaiting, what are
status,itemsanderror?
Open the HTML through a local web server. Opening it directly as a file can produce browser restrictions and paths that behave differently from HTTP.
Controlled failure
Temporarily change the URL to /data/missing.json. Predict the transitions, inspect the Network panel, and verify that the interface leaves loading and shows an error. Restore the correct path afterward.
Say the observed path aloud: "not-started, then loading, then error." Naming the transition is more useful than memorizing the catch block.
What to remember
Loading, empty and error are different facts. Represent them in state, render them intentionally and debug from network evidence toward state and DOM.