Questions
24 of 27
1What are client components?
2How to implement client rendering in next js?
3Describe how client components are rendered.
4How to decide what part should be rendered on the server and what on the client?
5Combining client and server components
6How to render a server component in the client component?
7Discuss best approaches with client components.
8Does using 'use client' ensure that the component only renders on the client?
9Explain the full lifecycle of a CSR page in Next.js — from initial HTML delivery to interactive UI.
10What is the difference between useEffect data fetching and React Query / SWR in a CSR context?
11When would you choose CSR over SSR or SSG in a production Next.js app? Give real-world examples.
12How does React's concurrent rendering model affect CSR behaviour in Next.js 13+?
13How do you handle deeply nested Client Components without causing unnecessary re-renders?
14Explain the concept of "client component boundaries" — how do they affect the component tree?
15How would you implement optimistic UI updates in a CSR-heavy Next.js application?
16What are the challenges of using Context API at scale in a CSR and SSR? How do you solve them?
17How does next/dynamic work? How is it different from React's lazy() and Suspense?
18What is the "flash of unstyled/unloaded content" problem in CSR, and how do you prevent it?
19How do you prefetch data for CSR pages in Next.js to reduce perceived latency?
20How do useMemo and useCallback help performance in CSR components? When are they overkill?
21How do you implement skeleton screens or loading states for CSR data fetching?
22Compare SWR vs React Query vs useEffect for client-side data fetching — when do you use each?
23How do you implement infinite scrolling or pagination purely on the client side in Next.js?
24How do you handle race conditions in CSR data fetching with useEffect?
25What is the difference between client-side fetch and server actions in Next.js App Router?
26How do you cancel in-flight API requests when a component unmounts in CSR?
27How would you handle real-time data (WebSockets / SSE) in a Next.js CSR component?
24 / 27

How do you handle race conditions in CSR data fetching with useEffect?

Handle race conditions in useEffect by using cleanup functions to set a flag (isMounted), using AbortController to cancel in-flight requests, or simply switching to data fetching libraries like SWR or React Query that handle this automatically

Race conditions in client-side data fetching occur when a component fetches data multiple times in rapid succession, and responses arrive out of order—an older request completes after a newer one, overwriting the latest data with stale information. This is particularly common in scenarios like search inputs, tab switching, or route changes. In useEffect, race conditions happen because there's no built-in mechanism to cancel pending requests when dependencies change. You must manually handle cleanup to ensure that only the most recent request updates the component state.

The Race Condition Problem
Solution 1: Mounted Flag Pattern
Solution 2: AbortController (Cancel Requests)

Another approach is using useRef to track the current request and ignore outdated responses. This is useful when you can't cancel requests (e.g., with some third-party APIs) but need to ensure only the latest response updates state. The pattern involves incrementing a request counter and checking it in the response handler .

Solution 3: Request ID Tracking

The most robust solution is to avoid manual useEffect data fetching entirely and use libraries like SWR or React Query. These libraries handle request deduplication, caching, and race condition prevention out of the box. SWR automatically cancels stale requests when new ones are made, and React Query's query keys ensure that only the latest data for a given key is stored .

Solution 4: SWR (Automatic Race Condition Prevention)
Choosing the Right Solution
  1. 1

    Mounted flag (isMounted): Simplest solution for preventing updates after unmount, but doesn't stop the request itself from completing and wasting resources .

  2. 2

    AbortController: Best for modern browsers—actually cancels network requests, saving bandwidth and processing. Works with fetch and can be polyfilled .

  3. 3

    Request ID tracking: Useful when working with APIs that don't support cancellation (e.g., legacy XMLHttpRequest or certain SDKs) .

  4. 4

    SWR/React Query: The recommended approach for production applications—handles race conditions, caching, and many other edge cases automatically .