Skip to main content

Request on the first render

Short version: make the request in useEffect with an empty dependency array [] (only on the first mount), and remember cancellation and error handling. Here is a reliable template.

javascript
import { useEffect, useState, useRef } from "react"; export function UserOnce() { const [data, setData] = useState(null); const [error, setError] = useState(null); const [loading, setLoading] = useState(true); // A guard against the effect running twice in Dev mode (StrictMode) in React 18 const didRunRef = useRef(false); useEffect(() => { if (didRunRef.current) return; // don't let it run a second time in Dev didRunRef.current = true; const controller = new AbortController(); (async () => { try { setLoading(true); const res = await fetch("/api/user", { signal: controller.signal }); if (!res.ok) throw new Error(`HTTP ${res.status}`); const json = await res.json(); setData(json); // update state only if not cancelled } catch (e) { if (e.name !== "AbortError") setError(e); } finally { setLoading(false); } })(); // cleanup: cancel the request on unmount return () => controller.abort(); }, []); // ← only the first render (mount) if (loading) return <p>Loading...</p>; if (error) return <p>Error: {String(error.message || error)}</p>; return <pre>{JSON.stringify(data, null, 2)}</pre>; }

Important points

  • Why []: the effect runs once - when the component mounts.

  • StrictMode in Dev (React 18): effects can be called twice. The useRef flag above prevents a duplicate request in development. In production the effect runs once.

  • Cancelling the request: AbortController is a must-have, so you don't catch a setState on an unmounted component and don't waste the network.

  • Where to get parameters: if the request depends on props/state (for example, userId), include them in the dependencies:

    javascript
    useEffect(() => { // ...request with userId... }, [userId]);

and show loading when userId changes.

  • Alternative: libraries like TanStack Query (React Query) and SWR take care of caching, cancellation, retries, stale-while-revalidate, and so on, simplifying the code.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.