Server state and client state help manage data in web apps. Server state is data from the server, client state is data stored in the browser.
Server state vs client state in NextJS
/* Server state example: fetching data in Next.js server component */ export default async function Page() { const res = await fetch('https://api.example.com/data'); const data = await res.json(); return <div>{data.message}</div>; } /* Client state example: using useState in a React component */ import { useState } from 'react'; export default function Counter() { const [count, setCount] = useState(0); return ( <button onClick={() => setCount(count + 1)}> Count: {count} </button> ); }
Server state is usually fetched asynchronously and can be shared across users.
Client state is local to the user and changes instantly on interaction.
export default async function Page() { const res = await fetch('https://api.example.com/user'); const user = await res.json(); return <h1>Hello, {user.name}</h1>; }
import { useState } from 'react'; export default function Toggle() { const [on, setOn] = useState(false); return <button onClick={() => setOn(!on)}>{on ? 'ON' : 'OFF'}</button>; }
This example shows client state with a counter button that updates instantly on click. It also shows server state by fetching a post title from an API and displaying it.
import { useState } from 'react'; // Client state: count button function Counter() { const [count, setCount] = useState(0); return ( <div> <h2>Client State Example</h2> <button onClick={() => setCount(count + 1)} aria-label="Increment count"> Count: {count} </button> </div> ); } // Server state: fetch message export async function getServerSideProps() { const res = await fetch('https://jsonplaceholder.typicode.com/posts/1'); const post = await res.json(); return { props: { title: post.title } }; } export default function Page({ title }) { return ( <div> <Counter /> <h2>Server State Example: {title}</h2> </div> ); }
Server state updates when you fetch new data from the server or reload the page.
Client state updates immediately on user actions without needing to reload.
In Next.js, server state can be fetched in server components or data fetching methods like getServerSideProps.
Server state is data from the server, shared and fetched asynchronously.
Client state is local data in the browser, updated instantly by user actions.
Use server state for data from APIs, client state for UI interactions.
Practice
server state in Next.js?Solution
Step 1: Understand server state meaning
Server state is data that comes from the server, such as API responses or database queries, and is shared among users.Step 2: Compare with client state
Client state is local to the browser and changes instantly with user actions, unlike server state.Final Answer:
Data fetched from APIs or databases and shared across users. -> Option DQuick Check:
Server state = shared API data [OK]
- Confusing server state with client UI state
- Thinking server state is local to one user
- Mixing server state with CSS or styling
useState hook for client state in Next.js?Solution
Step 1: Identify correct useState syntax
useState returns an array with current state and a setter function, so destructuring with [state, setState] is correct.Step 2: Check each option
const [count, setCount] = useState(0) correctly usesconst [count, setCount] = useState(0). const [data, setData] = useState(fetch('/api/data')) wrongly calls fetch inside useState. const data = await fetch('/api/data') is an async fetch, not useState. const count = useState(0) misses destructuring.Final Answer:
const [count, setCount] = useState(0) -> Option AQuick Check:
useState returns [state, setter] array [OK]
- Calling async fetch inside useState
- Not destructuring useState result
- Assigning useState directly to a variable
import { useState, useEffect } from 'react';
export default function Example() {
const [serverData, setServerData] = useState(null);
useEffect(() => {
fetch('/api/data')
.then(res => res.json())
.then(data => setServerData(data.message));
}, []);
return {serverData ?? 'Loading...'};
}Solution
Step 1: Check initial state value
The stateserverDatastarts asnull, so the component shows 'Loading...' initially because of the nullish coalescing operator.Step 2: Understand useEffect fetch timing
The fetch runs after the first render, so the message from the API is not available immediately.Final Answer:
Loading... -> Option BQuick Check:
Initial state null shows fallback text [OK]
- Assuming fetch is synchronous and immediate
- Expecting undefined or null to render as text
- Ignoring useEffect timing
import { useState, useEffect } from 'react';
export default function DataFetcher() {
const [data, setData] = useState();
useEffect(async () => {
const res = await fetch('/api/data');
const json = await res.json();
setData(json);
}, []);
return <div>{data.message}</div>;
}Solution
Step 1: Check useEffect callback syntax
React'suseEffectcallback cannot be async directly; it should call an async function inside.Step 2: Identify correct fix
Wrap the async fetch logic inside a separate async function inside useEffect, then call it.Final Answer:
useEffect callback cannot be async directly -> Option AQuick Check:
Async function inside useEffect, not async callback [OK]
- Making useEffect callback async directly
- Not handling initial undefined state safely
- Assuming data.message exists before fetch
Solution
Step 1: Understand server state fetching
UsinggetServerSidePropsfetches data on the server before rendering, providing server state.Step 2: Manage client state for filtering
Storing the fetched products inuseStateallows local filtering without refetching, which is client state.Final Answer:
Fetch products with getServerSideProps and store in client state with useState for filtering. -> Option CQuick Check:
Server fetch + client filter state = Fetch products withgetServerSidePropsand store in client state withuseStatefor filtering. [OK]
- Fetching data on every filter change
- Filtering on server for every user input
- Mixing server and client state responsibilities
Ready to prove it?
Pass the test and this pattern moves unknown
