React is often praised for being “declarative,” “efficient,” and “component-based.” But those words don’t mean much when you’re stuck wondering why your component re-renders every time you click a button. So let’s break it down—without the buzzwords. This post will help you understand: What triggers a re-render Why re-renders matter How to avoid unnecessary ones When to stop worrying and just build What triggers a re-render Why re-renders matter How to avoid unnecessary ones When to stop worrying and just build Let’s start from the beginning. What is a "Render" in React? When we say React renders a component, it simply means: React renders a component React runs your component’s function to figure out what it should look like on the screen. React runs your component’s function to figure out what it should look like on the screen. That’s it. Nothing magical. If you have this component: function Greeting() { return <h1>Hello, world!</h1>; } function Greeting() { return <h1>Hello, world!</h1>; } React “renders” it by calling Greeting() and putting <h1>Hello, world!</h1> into the DOM. Greeting() <h1>Hello, world!</h1> What Triggers a Re-render? A component re-renders when: Its state changes (via useState) Its props change (data passed from the parent) Its parent re-renders Its state changes (via useState) state useState Its props change (data passed from the parent) props Its parent re-renders parent Let’s look at each. 1. Re-render from State Change function Counter() { const [count, setCount] = React.useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}>Click me</button> </div> ); } function Counter() { const [count, setCount] = React.useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}>Click me</button> </div> ); } Every time you click the button, setCount updates the state, so React calls Counter() again to get the latest UI. setCount Counter() 2. Re-render from Prop Change function Greeting({ name }) { return <h1>Hello, {name}!</h1>; } function App() { const [name, setName] = React.useState("Alice"); return ( <div> <Greeting name={name} /> <button onClick={() => setName("Bob")}>Change Name</button> </div> ); } function Greeting({ name }) { return <h1>Hello, {name}!</h1>; } function App() { const [name, setName] = React.useState("Alice"); return ( <div> <Greeting name={name} /> <button onClick={() => setName("Bob")}>Change Name</button> </div> ); } When you change the name from "Alice" to "Bob", Greeting re-renders—because the name prop changed. Greeting name 3. Re-render from Parent Re-rendering Even if a child’s props didn’t change, it may still re-render if the parent re-renders. function Child() { console.log("Child rendered"); return <p>Child</p>; } function Parent() { const [count, setCount] = React.useState(0); return ( <div> <Child /> <button onClick={() => setCount(count + 1)}>Click</button> </div> ); } function Child() { console.log("Child rendered"); return <p>Child</p>; } function Parent() { const [count, setCount] = React.useState(0); return ( <div> <Child /> <button onClick={() => setCount(count + 1)}>Click</button> </div> ); } Even though Child has no props or state, it still logs “Child rendered” every time you click—because its parent re-rendered. Child parent Why Does This Matter? Re-renders aren’t bad. React is fast. You usually don’t need to worry. But in bigger apps, unnecessary re-renders can: Slow things down Trigger flickers Waste memory Slow things down Trigger flickers Waste memory So it's good to know how to avoid them when they actually cause problems. when they actually cause problems How to Avoid Unnecessary Re-renders ✅ Use React.memo to Skip Renders React.memo Wrap a component with React.memo() so it only re-renders if props change. React.memo() const Greeting = React.memo(function Greeting({ name }) { console.log("Greeting rendered"); return <h1>Hello, {name}</h1>; }); const Greeting = React.memo(function Greeting({ name }) { console.log("Greeting rendered"); return <h1>Hello, {name}</h1>; }); Now, Greeting will only re-render if the name prop changes. Greeting only re-render if the name Perfect when: The component is pure (no side effects) You’re passing the same props repeatedly The component is pure (no side effects) pure You’re passing the same props repeatedly ✅ Use useCallback to Avoid Changing Functions useCallback React sees a new function as a new prop—even if it does the same thing. function Parent() { const [count, setCount] = React.useState(0); const handleClick = () => { console.log("Clicked"); }; return <Child onClick={handleClick} />; } function Parent() { const [count, setCount] = React.useState(0); const handleClick = () => { console.log("Clicked"); }; return <Child onClick={handleClick} />; } This will cause Child to re-render every time—even if nothing else changes—because handleClick is a new function on every render. Child handleClick new function Fix it with useCallback: useCallback const handleClick = React.useCallback(() => { console.log("Clicked"); }, []); const handleClick = React.useCallback(() => { console.log("Clicked"); }, []); Now React can compare and see it’s the same function each time. same function ✅ Use useMemo to Avoid Recalculating Stuff useMemo If you’re doing expensive calculations in a component, wrap them in useMemo. useMemo const result = React.useMemo(() => { return slowFunction(input); }, [input]); const result = React.useMemo(() => { return slowFunction(input); }, [input]); This way, slowFunction only runs when input changes—not on every render. slowFunction input When Should You Care About Re-renders? Let’s be honest: Most of the time, you shouldn’t. Most of the time, you shouldn’t. Don’t optimize re-renders if: The app is fast The UI is smooth You're not debugging flickers or lag The app is fast The UI is smooth You're not debugging flickers or lag But start caring when: You see visual glitches (like flashing) You’re rendering lists with 100+ items You need pixel-perfect performance You see visual glitches (like flashing) You’re rendering lists with 100+ items You need pixel-perfect performance Common Misconceptions ❌ “React will re-render the entire app!” Not true. React is smart. It re-renders the components that need it, and it updates only the DOM elements that changed. components that need it ❌ “All re-renders are bad!” Nope. Re-rendering is how React works. Trying to avoid every re-render is a waste of energy. Focus on avoiding the wasteful ones. wasteful Final Thought: Focus on Clarity First It’s easy to get stuck chasing optimization before you’ve shipped anything. Here’s a better rule: Build first. Make it work. Then, if it feels slow—measure and improve. Build first. Make it work. Then, if it feels slow—measure and improve. That’s how you grow as a React developer. TL;DR React renders by calling your components to get updated UI State, props, or parent changes trigger re-renders Re-renders aren’t bad, but avoid unnecessary ones in large apps Use React.memo, useCallback, and useMemo when needed Don’t stress about it unless your app feels slow React renders by calling your components to get updated UI State, props, or parent changes trigger re-renders Re-renders aren’t bad, but avoid unnecessary ones in large apps Use React.memo, useCallback, and useMemo when needed React.memo useCallback useMemo Don’t stress about it unless your app feels slow