Introduction to Side Effects: Managing External Logic in React
Learn why side effects like API calls belong in the useEffect hook. Distinguish between rendering and side effects to build predictable React applications.
Previously in this course, we mastered Introduction to React State: Making Your UI Interactive to keep our components dynamic. While state manages the data that drives your UI, your application eventually needs to "reach out" to the world beyond your component’s internal logic. This lesson introduces side effects, the primary mechanism for handling these external interactions.
What Are Side Effects?
In Introduction to Component-Based Architecture in React, we discussed how React components should ideally be "pure." A pure function (or component) calculates its output based solely on its inputs (props and state) without modifying anything outside its scope.
A side effect is any operation that reaches outside the component to interact with the world. Common examples include:
- Fetching data from an API.
- Manually changing the document title or interacting with the DOM.
- Setting up timers or subscriptions.
- Logging data to an external analytics service.
If you perform these actions directly inside the body of your component function, you break the contract of purity. Because React calls your component function every time it needs to re-render, any code placed directly in the function body will execute every single time the component renders. This leads to performance bottlenecks, infinite loops, and erratic UI behavior.
Distinguishing Rendering from Effects
To understand the difference, think of your component as a calculation engine:
- Rendering: This is the process of calculating what the UI should look like based on current props and state. This should be fast, predictable, and free of side effects.
- Effects: These are the "after-effects" of the render. They happen after React has updated the DOM.
By separating these, you allow React to handle the UI update efficiently while you handle the "messy" external work in a controlled environment.
The Role of useEffect
React provides the useEffect hook to encapsulate these side effects. By wrapping your logic in useEffect, you tell React: "Do not run this code during the render phase. Wait until the component has finished painting the UI to the screen."
Here is the basic syntax:
JAVASCRIPTimport { useEffect } from CE9178">'react'; function MovieBrowser() { useEffect(() => { // Your side effect logic goes here console.log("The component has rendered or updated."); }); return <div>Movie Browser</div>; }
Worked Example: Updating the Document Title
Let’s advance our movie-browser project. Suppose we want the browser tab title to reflect the movie search query as the user types.
We shouldn't try to manipulate document.title directly inside the component body, as it would re-run on every single keystroke, causing unnecessary overhead. Instead, we use useEffect.
JAVASCRIPTimport { useState, useEffect } from CE9178">'react'; function MovieSearch({ query }) { // We use the state we learned in previous lessons const [resultsCount, setResultsCount] = useState(0); useEffect(() => { // This runs AFTER the render document.title = CE9178">`Searching for: ${query}`; }); return ( <div> <h1>Movie Browser</h1> <p>Results for "{query}": {resultsCount}</p> </div> ); }
By moving the title update into useEffect, we ensure that the React component remains focused on its primary job—returning JSX—while the browser title is updated as a secondary, synchronized operation.
Hands-on Exercise
In your movie-browser project, locate your main search component.
- Import
useEffectfrom 'react'. - Inside your component, add a
useEffectblock that logs the current search query to the console. - Observe the console when you type in the search bar. Notice how the log appears after the render is committed to the screen.
Common Pitfalls
- Performing Side Effects in the Render Body: Never put
fetch()calls orlocalStoragewrites directly in the function component body. It will trigger infinite loops because an API call usually updates state, which triggers a re-render, which triggers the API call again. - Assuming Execution Order: Beginners often expect effects to run synchronously. Remember that effects are scheduled and run after the browser has painted the screen.
- Forgetting to Manage Dependencies: While we will cover this in the next lesson, be aware that an
useEffectwithout a dependency array will run after every render. This is rarely what you want.
Recap
Side effects are necessary for real-world applications, but they must be isolated from the render logic to maintain performance and predictability. The useEffect hook is your tool for scheduling these operations to run after React has committed updates to the DOM. By keeping your render function pure and pushing side effects into useEffect, you ensure your app remains performant and easy to debug.
Up next: useEffect Dependencies — learn how to control exactly when your effects run so you don't trigger unnecessary API calls or DOM updates.
Work with me

Next.js Full-Stack Web App Development
A fast, SEO-ready full-stack web app built with Next.js 16 — from idea to deployed product, by an engineer who ships to production.

Headless WordPress + Next.js Frontend Development
Keep WordPress for content, get a lightning-fast Next.js frontend. The best of both worlds — familiar editing, modern speed.