Question presented to candidate: "How would you structure the code that talks to your backend? Not just the request — the whole integration."
What a strong answer should cover:
- Layering is the actual answer: components → a data hook → an API client module → the network. Components should not know about URLs, headers, or transport.
- The API client centralises the base URL, auth headers, JSON parsing, error normalisation, timeouts, and retries — so those exist once, not per call site.
fetchdoes not reject on HTTP errors. A 404 or 500 resolves withok: false; you must check it or every failure looks like success.- Normalise errors into one shape so components handle failure uniformly.
- Auth: attach the token in the client, refresh on 401, and never keep secrets in client-side environment variables — anything in the bundle is public.
- Cancellation with
AbortController, and retries only for idempotent requests with backoff. - The consuming layer: a query library, or a custom hook wrapping the client.
- CORS is a browser-enforced server configuration, not something you fix in React.
- GraphQL changes the shape (one endpoint, client-specified queries) but not the layering.
Clarifying questions expected:
- "REST or GraphQL, and is there an existing client or generated types?"
- "How is auth handled — cookies or a bearer token we manage?"
- "Do we have a framework where this could be a server-side call instead?"
Code / implementation expected: Yes — a small API client with error normalisation, and a hook consuming it.