Myths about useEffect
Some common mistakes I see people make with useEffect and how to avoid them.

If you've been building for the web for a while, you probably remember the days
when making a page interactive meant sprinkling <script>
tags throughout your
HTML, hoping everything loaded in the right order, and wrestling with global
variables. If you wanted a dynamic search box or a fancy dropdown, you'd either
write a bunch of jQuery or wire up some custom JavaScript, and then cross your
fingers that it played nicely with your backend-rendered HTML.
Fast forward to today, and React's new Server Components model takes a completely different approach. Now, you can compose your UI out of both server and client components, letting each do what it does best. And the best part? You get to include interactive client components right in your server-rendered UI—no script tag gymnastics required.
Let's dig into why this is such a big deal, and how it works in practice.
Back in the day, if you wanted a page that showed a list of products (rendered on the server) and let users filter them with a search box (handled on the client), you'd end up with something like this:
<!-- Server-rendered HTML --><input type="search" id="search" /><ul id="products"> <li>Product 1</li> <li>Product 2</li> <!-- ... --></ul><!-- Client-side search functionality --><script src="/static/search.js"></script><script> window.initSearch({ selector: 'ul' })</script>
You had to make sure your scripts loaded after the HTML, and that your
JavaScript could find and hook into the right DOM nodes. If you wanted to pass
data from the server to the client, you'd often have to serialize it into a
<script>
tag or a data-*
attribute. It worked, but it was fragile and hard
to scale.
With React Server Components (RSCs), you can build your UI as a tree of components, some of which run on the server (fetching data, rendering markup), and some of which run on the client (handling interactivity, managing state). The magic is that you can compose these together—server components can render client components as children, and everything just works.
Here's what that looks like in practice:
// Server componentimport { SearchBox } from './search-box.js' // a client componentexport default async function ProductList() { const products = await fetchProductsFromDatabase() return ( <div> <SearchBox> <ul> {products.map((product) => ( <li key={product.id}>{product.name}</li> ))} </ul> </SearchBox> </div> )}
The SearchBox
is a client component—maybe it uses state, effects, or context.
But you can include it directly in your server-rendered UI. No need to wire up
script tags or global variables. React takes care of sending just the code
needed for SearchBox
to the client, and hydrates it so it's fully interactive.
In the EpicReact.dev Server Components workshop, we build a UI that lets users search for spaceships and view details. Here's how the composition works:
No script tags. No manual hydration. Just components.
Let's compare the two approaches:
Old Way (Backend Framework) | React Server Components |
---|---|
Server renders HTML | Server renders UI (as React elements) |
Client JS finds DOM nodes | Client components are included directly |
Data passed via script tags or data-* | Data fetched where it's needed |
Manual hydration | Automatic hydration of client components |
Hard to scale, fragile | Encapsulated, composable, robust |
One of the biggest pain points in React apps has always been prop
drilling—passing data through layers of components just to get it where it's
needed. With RSCs, you can fetch data right where you need it (thanks to async
server components), and you can use platform features like Node's
AsyncLocalStorage
to avoid prop drilling for global values. (Check out the
workshop exercise on this
for more.)
Composing server and client components together is the modern React's superpower. You get the best of both worlds: fast, data-rich UIs from the server, and rich interactivity from the client—without the pain of the old days. If you haven't tried building with React Server Components yet, now's the time. Your future self (and your users) will thank you.
Want to learn more? Check out the EpicReact.dev Server Components workshop for hands-on exercises and deep dives into these concepts.
Delivered straight to your inbox.
Some common mistakes I see people make with useEffect and how to avoid them.
I still remember when I first heard about React. It was January 2014. I was listening to a podcast. Pete Hunt and Jordan Walke were on talking about this framework they created at Facebook that with no support for two way data-binding, no built-in HTTP library, no dependency injection, and in place of templates it had this weird XML-like syntax for the UI. And to top it all off, I was listening to it while driving to the first ever ng-conf.
Excellent TypeScript definitions for your React forms
Build flexible, declarative UIs like native HTML with Compound Components—a powerful React pattern you’ll master at EpicReact.dev.