As we all know, Server Components are not allowed to use hooks like useState and useEffect—but why?
🚧 Understanding the Request Flow
Let’s start from a typical page request. When a request comes in (and possibly hits the cache), it flows through several key functions:
handleResponsedoRenderrenderToHTMLOrFlightImplgenerateCacheEntry
👉 generateCacheEntry is the core of Next.js caching strategy.
🔑 Key Parameters in generateCacheEntry
From the function signature, we can identify some critical parameters:
encodeCacheKeyPartsfn(the actual render function)
🧩 Cache Keys and Server References
Taking a deeper look at encodeCacheKeyParts, we notice something important:
It generates keys that match those in
server-reference-manifest.json.
This connects directly to concepts discussed in the previous article.
- Each page/component has a corresponding cache key
- These keys are heavily used across Next.js internals
⚙️ The Core Execution: generateCacheEntryImpl
Continuing down the call stack, we reach:
generateCacheEntryImpl— where rendering actually happens
Here, we encounter a key variable:
requestPromise
💡 This is crucial:
- Server Components can be
asyncfunctions requestPromiserepresents the execution of the component itself- Once resolved, the result is streamed to the client
⏱️ Cache Expiration Strategy
Next.js also implements a time-based cache invalidation strategy:
- When
cacheis invoked:- It calculates the current time
- Compares it with the expiration time defined by the developer
- Based on this, it decides:
Should we reuse the cache or regenerate it?
🗂️ Cache Retrieval
Cache entries are retrieved using:
- Page key
- Page path (
serializedCacheKey)
📌 Example
For the URL:
http://localhost:3000/blog/2
- The dynamic parameter:
{"id": 2}
This value becomes part of the cache key
🧠 So… Why No Hooks in Server Components?
Now that we understand the flow, the reason becomes clearer:
Server Components are designed to be pure, stateless, and cacheable.
Hooks like useState and useEffect:
- Depend on client-side lifecycle
- Require persistent state between renders
But Server Components:
- Are executed once per request (or cache hit)
- Produce a deterministic output
- Are serialized and streamed
👉 Allowing hooks would break caching, determinism, and streaming guarantees.
✅ Key Takeaway
Server Components trade interactivity for performance and scalability.
They work because they are:
- Stateless
- Deterministic
- Cache-friendly
And that’s exactly why hooks like useState and useEffect are not allowed.






Top comments (0)