What if your app could magically keep data fresh and smooth without you juggling updates?
Server state vs client state in NextJS - When to Use Which
Imagine building a web app where you fetch user data from a server and also let users update their profile locally. You try to keep track of all changes manually, syncing between what's on the server and what's on the user's screen.
Manually managing server and client data is confusing and error-prone. You might show outdated info, overwrite changes, or cause slow updates. It's like juggling two balls and dropping one every time.
Using clear server state and client state separation helps your app know exactly where data lives and when to update it. Frameworks like Next.js make syncing smooth and automatic, so your app stays fast and reliable.
fetch('/api/user').then(res => res.json()).then(data => { this.user = data; }); // manual update and sync
const user = useServerState('/api/user'); const localChanges = useClientState(user); // automatic sync and update
This lets your app stay in sync with the server while keeping a smooth, interactive experience on the client side.
Think of a social media app where your profile info updates instantly on your screen while also saving changes safely on the server without losing anything.
Manual syncing of server and client data is tricky and causes bugs.
Separating server state and client state makes data flow clear and reliable.
Next.js and similar tools help automate this, improving app speed and user experience.
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
