Welcome to the first lesson of this course, where we will set up the API client for your project. In modern web applications, the frontend (what users see and interact with) often needs to communicate with the backend (where data and business logic live). In our case, the frontend is built with React, and the backend uses NestJS.
To make this communication possible, we use an API client. The API client is a set of functions that help your React app send requests to the backend and handle the responses. Setting up this client is the first step in allowing your app to fetch data, show updates, and interact with users in real time.
This lesson makes your React app capable of talking to the backend by creating a small, environment-aware API client and then verifying connectivity from HomePage. We will:
- Define environment helpers and base URL candidates (
isBrowser,isLocalhost,PORT_HOST,cachedBase,BASE_CANDIDATES) and explain them in depth. - Centralize endpoint paths in a
pathshelper. - Implement a tiny fetch-based
apiClientand ahello()function that calls/api/hello. - Use
useEffectin to test the API status and display a user-friendly indicator.
Let’s look at the main parts of the API client, which lives in src/api/client.ts. Here is the code:
Let’s break this down:
-
Centralized endpoint paths:
paths.hello()returns the canonical string"/api/hello". Keeping paths in one object avoids typos and makes future refactors (e.g., prefix changes) a single-edit operation. -
Hello call flow:
hello()performsapiClient.get(paths.hello()), which sends a GET request to/api/hello. It logs successes for dev visibility, throws on errors to let the caller decide how to handle failures, and returns the parsed JSON (the backend “envelope”). -
Expected envelope: For this endpoint, the backend replies with
{ success: true, data: "Hello World!" }. Your UI readssuccess(for status) and may readdata(the string) for confirmation. -
hellois an asynchronous function. It uses to wait for the API response.
Now, let’s see how the API client is used in the React frontend. Here is the relevant part of src/pages/HomePage.tsx:
Here’s what’s happening:
- The
HomePagecomponent uses React’suseStateanduseEffecthooks. - When the page loads, it calls the
hellofunction from theAPI client. - If the backend responds with
{ success: true }, it sets the status to "Connected." - If there is an error or the response is not successful, it sets the status to "Connection Failed."
- The status is displayed on the page, so users can see if the frontend is able to talk to the backend.
Let's break down the usage of the useEffect hook we saw in the HomePage.tsx component.
-
State Setters (
setServerStatus,setHelloMessage)useStatereturns a getter and a setter. Calling a setter schedules a re-render with the new value.- We initialize
serverStatusto"Checking..."so the UI communicates that a health check is in progress. - When a response arrives, we flip it to
"Connected"or"Connection Failed". If we receive a greeting string indata, we store it inhelloMessage.
-
The Effect Lifecycle
- The effect runs once after the first render because the dependency array is
[]. - Inside the effect, we call
hello()which returns a promise resolving toApiEnvelope<string>. - When the promise resolves successfully, we and from the envelope. This mirrors the backend’s global response contract.
- The effect runs once after the first render because the dependency array is
- Environment helpers make URLs portable across local dev, sandboxed ports, and same-origin reverse proxies.
- A shared
pathsobject removes stringly-typed endpoints and helps avoid typos. - Returning the envelope from
hello()keeps the calling UI consistent with other endpoints that will be added later. - The
useEffectpattern with anisMountedguard is robust for small health checks and scales to more complex data fetching where cancellation or staleness matters.
With this foundation, your frontend speaks reliably to the backend and communicates status clearly to users and developers. Next, you can build additional client helpers (auth, books, shelf) using the same envelope pattern and paths registry.
Let's review our apiClient code and understand what it does. We'll start with Environment Detection.
Note: This is a deep dive section: it explains why the code is structured the way it is, how environment detection works, and how requests are retried across base URLs.
Understanding this is valuable for debugging and scaling later, but it’s not mandatory — you can skim it now and return later if something breaks.
-
Environment Detection:
These lines check if the code is running in a browser and if it’s running on your local machine. This helps the client know how to build the correct URL for API requests.
isBrowser- Checks
typeof window !== 'undefined'. - Why: In SSR/tests,
windowdoesn’t exist. This flag prevents accidental use of browser-only APIs and lets you adapt URL building to the runtime.
-
isLocalhost- Verifies the hostname is exactly
localhostor .
- Verifies the hostname is exactly
Note: This section is another deep dive into how our generic request function works under the hood.
While it’s useful to understand each stage (headers, candidate URLs, parsing, error handling), you don’t need to memorize all the details to use the API client effectively.
Think of this as "peeking behind the curtain" — a great way to build intuition, but optional if you just want to focus on building features.
- Headers assembly:
- Adds
Content-Type: application/jsononly when a body exists; merges user-supplied headers. Keeps GET requests lean and standards-compliant.
- Adds
- Candidate loop:
- Uses
cachedBaseif known; otherwise iteratesBASE_CANDIDATES. Buildsurl = base + pathand performs .
- Uses
In this lesson, you learned how to set up an API client to connect your React frontend to your NestJS backend. We covered:
- Why an
API clientis important - How the client code detects the environment and chooses the right base URL
- How to make a simple API call to the backend
- How to use the
API clientin a React component to show the connection status
You are now ready to practice making and using API calls in your own code. In the next exercises, you will get hands-on experience with these concepts, helping you build confidence in connecting your frontend and backend.
