
If you've written even a small React app, you've probably wondered:
"Why did my component render again?"
"Why is React re-running my function?"
"What exactly triggers a re-render?"
"Does every state update cause a re-render?"
"Should I worry about unnecessary renders?"
These questions are extremely common even experienced developers revisit them.
Rendering and re-rendering are core behaviors of React. Once you understand them deeply, React becomes predictable, easy, and logical. This blog explains rendering the way a senior developer would explain it to a beginner humanized, simple, and without code.
Rendering is the process where React takes your component's output (JSX) and figures out what the UI should look like.
In simple words:
Rendering is React's way of describing the UI.
During rendering, React:
runs your component function
evaluates your JSX
builds a virtual representation of the UI
prepares the blueprint for what to show on the screen
Rendering does NOT mean updating the real screen immediately.
Rendering simply creates the plan.
The actual update to the browser happens in the commit phase, not during the render.
Re-rendering means React has decided that something changed and needs to re-run your component to see what the updated UI should look like.
Think of it like this:
If your component were a recipe, re-rendering is React re-reading the recipe to see if anything has changed.
If the ingredients (state, props, context) change the recipe must be re-read.
React re-renders components when:
A component's state changes
If you update state in a component, React re-renders that component.
A component receives new props
If the parent sends new data, the child re-renders.
A parent component re-renders
When a parent re-renders, all children re-render by default.
A context value used by the component changes
Any component consuming context will re-render when the context updates.
A hook dependency changes
For example, effects re-run when dependencies change.
Strict Mode (dev only) intentionally re-renders components twice
This helps you catch bugs and side-effect issues.
These are the fundamental triggers.
Beginners often panic:
"My component re-rendered! This is bad!"
No.
Rendering is NORMAL.
Re-rendering is NORMAL.
React is designed to re-render efficiently.
Instead of avoiding re-renders completely, the real skill is understanding them and optimizing only when necessary.
React's UI update process has two distinct phases:
React calls your components
Builds Virtual DOM
Compares with previous virtual state
Identifies what needs updating
This phase is pure, interruptible, and does not touch the real DOM.
React updates the real DOM
Applies changes to actual elements
Browser paints the final UI
This is the phase that the user sees.
Render = Thinking
Commit = Doing
React "thinks" first, then "does."
React uses a lightweight in-memory representation of the UI called:
The Virtual DOM
When your component renders, React:
Creates a new Virtual DOM snapshot
Compares it with the old one (diffing)
Finds exactly what has changed
Updates only those parts in the real DOM
Without Virtual DOM, re-rendering would be extremely slow.
When a component renders, React:
Calls the component function
Evaluates all variables inside it
Evaluates JSX
Builds a virtual UI description
Prepares a list of DOM mutations
Applies changes in the commit phase
Rendering does not directly update the screen React uses this process to stay fast and predictable.
Even if only one part of the UI React changes, React may re-render entire branches of the component tree.
Why?
Because rendering is cheap.
Real DOM updates are expensive, but Virtual DOM computations are fast.
React prefers:
frequent renders
minimal DOM updates
This is why React stays fast even in large apps.
If you remember only one section, remember this:
React re-renders a component when:
State belongs to a component. If state updates → component re-renders.
If a parent sends new props → child re-renders.
If a component consumes context → updates trigger re-render.
Every re-render in React comes from one of these three.
Imagine you're building a counter.
When the user clicks "+1," state changes.
A changed state = component re-renders.
During re-render:
React calls the component again
JSX is evaluated again
The Virtual DOM updates
React updates only the number on the screen
The whole component re-runs, even if only one number changed.
Imagine you have:
A parent component
A child component that displays a name
If the parent sends a new name through props:
→ child must re-render
→ React re-runs the child component
→ UI updates accordingly
This is how React ensures the UI always stays in sync with the data.
When a parent re-renders:
All of its children re-render
Even if their props didn't change
This is normal and expected.
Why?
Because React needs to re-run children to ensure consistency.
React re-renders components whose state or props changed NOT just the small part of the UI.
React does NOT re-render individual elements.
React re-renders entire components then updates the UI efficiently.
Rendering ≠ DOM update.
React compares the Virtual DOM first.
If nothing changed, it updates nothing on the screen.
This is React's power.
React re-renders:
often
aggressively
intentionally
And that's okay.
React is optimized for this behavior.
You only need to optimize re-renders when:
performance drops
component trees get huge
repeated renders slow down UI
90% of the time, React's defaults are perfect.
Because beginners see:
component functions running again
console logs repeating
unexpected useEffect calls
changes they didn't expect
This creates the illusion that something is wrong.
But in React:
Re-running is normal.
Re-rendering is expected.
Re-evaluating is routine.
React workloads are tiny and efficient.
If you use React Strict Mode, React will intentionally run components twice to detect side-effect problems.
This happens ONLY in development.
In production, everything runs once.
Strict Mode helps you:
catch missing cleanups
catch unsafe logic
catch side-effect bugs
useEffect runs AFTER the component renders.
If a dependency changes:
Component re-renders
useEffect runs again
Cleanup (if needed) runs before re-running
If you misunderstand rendering, useEffect feels unpredictable.
Once you understand rendering, useEffect becomes logical.
Updating state unnecessarily
Beginners often update state even if the new value is the same.
Storing values in state that don't need to be there
Derived values should not be in state.
Passing inline objects/functions as props
React sees them as "new" on every render.
Using context for too many values
Context re-renders every consumer when changed.
Not understanding parent-child relationships
If a parent re-renders, children follow.
Only when:
your UI feels slow
hundreds of components re-render unnecessarily
expensive logic runs repeatedly
lists are large
animation lags occur
React is already fast.
Premature optimization causes more issues than it solves.
React Rendering and re-rendering might feel complex at first, but the core ideas are simple:
Components render when state, props, or context change.
Rendering is cheap; DOM updates are optimized.
React re-renders entire components, not fragments.
Re-rendering is normal not a performance issue.
Virtual DOM ensures only necessary updates hit the screen.
Master rendering, and React becomes predictable, stable, and enjoyable.
AnNo. Only components affected by state/props/context re-render.
Not usually. React is optimized for frequent re-renders.
Yes any change to state inside a component re-renders it.
Yes, unless optimized with special patterns.
No. Rendering updates the Virtual DOM; the real DOM updates only if needed.
Because of Strict Mode only during development.
React allows optimizations, but avoid them unless necessary.
.png)
You've probably heard people say things like:
"React is everywhere."
"Most modern frontends use React."
"Learn React if you want a job in web development."
But when you finally decide to start, one question hits you:
"How do I actually build my first React app, step by step?"
This guide is written exactly for that moment.
No assumptions that you already know everything.
No overwhelming jargon.
Just a clear, structured, step-by-step path from:
"I don't know where to start"
to
"I built and ran my first React app."
By the end, you will understand not only what to click and type, but also why you are doing each step. That understanding is what turns you from a copy-paster into a real developer.
Before touching any tools, get clarity: what will your first React app be?
For a first project, keep it small and achievable. A good starter app could be:
A simple "Task List" (To-Do app)
A "Notes" list where you can add and delete notes
A "Movie Watchlist" with a title and status
A "Counter + Message" app that reacts when the count crosses a certain number
You learn the core ideas without getting lost.
You get a complete "idea → app" experience quickly.
You can actually finish it, which builds confidence.
For this guide, imagine you're building a simple Task List App:
You can see an input box and an "Add Task" button.
When you add a task, it appears in a list.
You can mark tasks as done or remove them.
Everything we talk about components, state, props, events will fit nicely into this simple app.
You do not need to be a JavaScript expert to start React, but you do need some basics:
HTML fundamentals (div, h1, p, input, button)
CSS basics (classes, simple styling)
JavaScript basics:
variables (let, const)
functions
arrays and objects
basic events and conditions
If these concepts are at least somewhat familiar, you're ready to move into React.
To build a React app, you typically need:
Node lets you run JavaScript tools on your machine.
npm (Node Package Manager) helps you install libraries like React.
Visual Studio Code is the most popular choice. It gives:
syntax highlighting
extensions
built-in terminal
Chrome, Edge, Firefox etc. with DevTools for debugging.
Your development setup is like your "workbench." Once it's ready, React development becomes much smoother.
Today many developers use modern React toolchains like Vite, Next.js, or older tools like Create React App.
For a first app, the exact tool is less important than understanding what it gives you:
A starting folder structure
A development server
Basic configuration already done
React and ReactDOM installed
You run a command once, and you get a ready-made React project structure you can start editing. Think of it as starting with a template instead of a blank page.
Once the project is created, you'll typically see a folder with files like:
package.json – list of dependencies and scripts
src/ – where your actual React code lives
public/ or similar – static files like favicons
index.html – the base HTML shell that React will "attach" to
Every modern React setup gives you a development server.
It runs locally (on something like http://localhost:3000/ or a similar port).
It shows your app in the browser.
It automatically reloads when you save files.
This gives you a fast feedback loop:
Change your code.
Save.
Instantly see the change in your browser.
That loop is what makes React development feel interactive and fun.
In almost every React app, there's a file like:
main.jsx or
index.jsx (or .js)
This file is responsible for:
Importing React and ReactDOM
Importing your root component (often called App)
Telling React where in the HTML it should render the app
In the HTML file, there is usually a single root element like:
<div id="root"></div>
React takes over this div and controls everything inside it. Instead of manually writing HTML, you describe UI using React components, and React updates the DOM for you.
Your App component is typically located in src/App.jsx or src/App.js.
Conceptually, App is:
the "main screen" of your application
a React function that returns what should be shown on the screen
the place where you'll first add your layout and structure
Think of App as the root box of your UI. Inside this box, you will create:
headings
input fields
buttons
lists
child components
Eventually, your App will be composed of many smaller components like Header, TaskList, TaskItem, etc.
JSX is what makes React feel natural to many developers.
Instead of writing:
long JavaScript instructions to create and append elements
you write HTML-like syntax directly inside JavaScript.
For example, inside your App component, you might have:
a main heading
a section for your input and button
a section for your list of tasks
JSX lets you see your UI structure clearly, and React uses that to build its internal Virtual DOM and then render to the real DOM.
It looks like HTML, but it's not exactly HTML.
You can embed dynamic content and data inside it.
It helps you visually understand your component layout.
React is all about components.
For the Task List app, you might break it down into:
Header – shows the app title like "My Tasks"
TaskInput – input box + "Add Task" button
TaskList – list of all tasks
TaskItem – single task entry with a label and action buttons
Reusability: You can reuse TaskItem multiple times.
Clarity: Each file and component has a clear responsibility.
Maintainability: Changes in one area don't affect everything else.
Collaboration: Teams can work independently on different components.
At this point, your app structure is taking shape in your mind and in your files.
Until now, everything is static. To make the app interactive, you need state.
State is:
data that belongs to a component
data that can change over time
"remembered" across re-renders
For a Task List app, your state will include:
the current text in the input box
the list of tasks (each task might have text and completed status)
The usual pattern:
Use state in App (or a relevant parent component) to store the list of tasks.
Update that state when the user adds, completes, or deletes a task.
The UI automatically re-renders when state changes.
You don't manually re-draw the UI.
You change the state, and React re-renders for you.
Once your state is in place, you will want to pass parts of that state down to child components.
This is where props come in.
Props are:
inputs to components
read-only data passed from parent to child
how you customize each component instance
For example:
App passes the list of tasks to TaskList as a prop.
TaskList passes individual task details to each TaskItem.
App might also pass functions (as props) that let children trigger actions like "mark complete" or "delete".
This is how components talk to each other in React:
Data flows down through props.
Actions flow up through callback functions passed as props.
To make your app truly interactive, you'll handle events like:
when a user types in the input
when they click "Add Task"
when they click "Mark Complete"
when they click "Delete"
React gives you a clean way to handle these events with event handler functions.
Conceptually:
You create a function for the action (for example, handleAddTask).
You connect that function to the button's click event.
Inside the function, you:
read the current input value from state
update the list of tasks in state
The event handling pattern in React is:
User action
Event handler runs
State updates
React re-renders the UI
Once you understand that cycle, everything in React starts to make sense.
Your task list will likely be an array in state.
To show it:
You loop over the array.
For each item, you render a TaskItem component.
Each TaskItem receives props like task text and actions.
This is React's power:
Instead of manually building lists in HTML, you map data to components, and React renders them.
If the list grows, updates, or shrinks, React automatically updates the UI accordingly.
Even a simple app feels more professional with some basic styling.
You can:
Use plain CSS files imported into your components.
Use a global stylesheet.
Group styles logically: layout, buttons, input, list items.
For a first project, don't chase perfection in design.
Focus on:
clean spacing
readable fonts
clear buttons
consistent colors
Styling is what makes your first app feel "real" instead of a bare demo.
Before calling your app "done," use it like a real user:
Type a task and add it.
Add multiple tasks.
Remove a task.
Mark a task as done (if you added that feature).
Refresh the browser and see how it behaves.
Check how it looks on different screen sizes.
Your goal is not perfection but confidence that:
"Yes, this app works as I intended."
This validation is crucial. It builds trust in your skills and motivates you to build more.
Most React toolchains provide a command to build a production-ready version of your app.
This does things like:
optimize files
minify JavaScript
prepare the app for deployment
Even if you don't deploy your first app, it's good to know that:
development version is for building and testing
production build is for hosting or shipping
Later, you can deploy your app to platforms like Netlify, Vercel, or any static hosting service.
By the time you've built this first app, you've learned far more than it seems at first glance:
You now understand:
How a React project is structured
What a root component (App) is
How JSX describes UI
How components are composed
What state is and why it matters
How props pass data between components
How events trigger state changes
How React re-renders based on state
How to structure files and basic styling
This is not "just a toy app."
This is your foundation.
From here, building more complex apps is mostly a matter of:
repeating the same ideas
combining them in smarter ways
adding new tools (routing, forms, APIs, global state)
Once your first project is complete, the worst thing you can do is stop.
Here are some good "next step" projects:
A Weather App using a public API
A Notes App with categories
A Movie Search App using an external movies API
A Simple Expense Tracker
A Quiz App with multiple-choice questions
For each new app, you will:
practice components again
work more with state and props
handle more events
possibly integrate APIs
improve your UI thinking
Each project makes React feel more natural.
You don't need to be an expert, but you should be comfortable with basics like variables, functions, arrays, objects, and simple DOM ideas. The better your JavaScript, the smoother your React journey.
For beginners, any modern starter like Vite or Create React App is fine. The key is to understand what it gives you: a ready-to-use React environment with a dev server and basic structure.
If you follow clear steps and keep the project small, you can build your first simple React app in a day or even a few focused hours. The goal is understanding, not speed.
Focus on logic first: components, state, and props. Once the app works, improve the design. Clean structure is more important than fancy visuals at the beginning.
Yes React is beginner-friendly when you start small and focus on fundamentals. The ecosystem is huge, but you do not need everything on day one. Components, state, props, and events are enough to start.
No. You can add TypeScript later. For your first app, plain JavaScript is more than enough.
Build a second app. Then a third. Each project will deepen your understanding. Later, you can explore routing, context, hooks in detail, and integration with APIs.

When beginners start learning UI Full Stack web with React Hooks, almost everyone understands useState quickly but useEffect feels confusing.
Why does it run after the render?
Why does it depend on an array?
Why does it run multiple times?
Why does it trigger again when values change?
What are side effects anyway?
These questions are extremely common.
But once you understand what useEffect really does, it becomes one of the easiest and most powerful hooks in React.
This blog explains useEffect in the simplest possible way, using real-time, real-world examples not code and with absolute clarity.
useEffect is a React Hook that lets you run logic after React has rendered the UI.
This logic is usually something that:
React itself cannot do
must happen outside the rendering process
must occur because something changed
In technical terms:
useEffect handles "side effects" logic that lives outside the pure rendering flow.
When React renders the UI, it wants the process to be:
predictable
pure (only UI output)
consistent
fast
Anything that happens outside rendering is considered a side effect.
Examples of side effects:
fetching data from an API
updating document title
accessing browser storage
managing timers
subscribing to events
listening for scroll or resize
connecting to WebSockets
updating analytics
React cannot perform these tasks inside the render itself that's why useEffect exists.
useEffect is confusing at first because:
It runs after rendering
The dependency array affects when it runs
It may run again based on changes
It may run with cleanup logic
It affects performance if misused
It replaces multiple lifecycle methods like mount/update/unmount
But once you learn the rules, it becomes predictable.
When your component renders, React does this:
Render the UI
Commit the UI to the screen
Then run your useEffect callback
If dependencies change → React re-runs useEffect.
If component unmounts → React runs cleanup logic.
useEffect is tied to:
rendering
dependency changes
component lifecycle
All in one powerful hook.
The dependency array controls when useEffect runs.
It can be in 3 forms:
Runs after every render.
Runs only once, after the first render (on mount).
Runs whenever those values change.
This behavior allows you to control exactly WHEN logic runs.
Scenario: A user lands on a webpage.
You want to show:
"Welcome back!"
This should only run ONCE.
Where useEffect fits in:
useEffect with an empty dependency array runs only once perfect for:
welcome messages
page loads
analytics initialization
default data loading
first-time executions
This is useEffect simulating a "componentDidMount" behavior.
When a component loads, you want to fetch:
user profile
product list
notifications
dashboard analytics
You don't want to fetch repeatedly. Only ONCE.
useEffect solves this perfectly.
Using useEffect with an empty array ensures the API call runs once after initial load.
React cannot fetch data inside rendering, so useEffect is the ideal place for it.
Example:
You have a cart.
When items increase, you want the page title to show:
"Cart (3 items)"
This logic must run whenever the cart count changes.
useEffect dependency array helps:
Put cartCount in the dependency array now the title updates automatically on every change.
Imagine you want:
a sticky header
a "back to top" button
an animation when the user scrolls
lazy loading images while scrolling
You must listen to the scroll event something React doesn't do automatically.
useEffect is perfect for:
attaching scroll listeners
updating state based on scroll
cleaning up listeners after unmount
Event listeners belong inside effects because they are side effects.
Imagine an app where a user gets auto-logged out after 5 minutes of inactivity.
You would need:
a timer
a cleanup mechanism
state dependency
useEffect is ideal for:
starting timers
clearing timers
resetting timers on change
Timers cannot live inside render only inside useEffect.
Example:
A user selects dark mode.
You want to save the selection in localStorage.
You MUST access the browser API which is a side effect.
useEffect helps sync data whenever preferences change.
If you want responsive behavior like:
shrinking header
rearranging cards
adjusting layout
updating component sizes
You need the window width.
Window properties also must be accessed inside useEffect because they're outside React's rendering process.
Imagine:
A password strength meter
Live form validation
Checking if a username already exists
You want the validation to run every time the input changes.
Dependency-based useEffect is perfect for this.
When the user:
opens a page
clicks something
spends time on a section
scrolls to a point
Analytics tools like Google Analytics or Mixpanel must be triggered.
These are classic side effects.
Thus, useEffect handles these tasks.
Imagine you created:
a timer
an event listener
a WebSocket connection
an animation
a subscription
a long-running background process
When the component is removed, you MUST stop these processes.
useEffect allows cleanup using a returned function.
Cleanup prevents:
memory leaks
duplicate timers
stacked event listeners
unnecessary network calls
slow performance
unexpected behavior
It runs right before the component unmounts or before useEffect runs again.
In class components, developers had to use:
componentDidMount
componentDidUpdate
componentWillUnmount
useEffect replaces all three with one single hook.
It simplifies lifecycle management massively.
Missing dependency values
Causes incorrect or stale data.
Adding wrong dependencies
Leads to infinite loops.
Putting useEffect inside a condition
Breaks the rules of hooks.
Doing heavy logic inside useEffect
Hurts performance.
Not using cleanup
Leads to memory leaks.
Learning these early saves hours of debugging.
React uses the dependency array to:
compare old vs new values
detect changes
trigger re-runs
If the dependency hasn't changed → effect doesn't run.
If it has changed → useEffect executes.
This comparison is fast and optimized by Fiber.
Without useEffect, React apps would not be able to:
fetch data
control browser APIs
respond to user actions
update based on state changes
handle subscriptions
manage animations
sync with external systems
useEffect is the bridge between React's internal world (rendering) and the outside world (everything else).
Once you understand:
side effects
dependency arrays
cleanup functions
how React renders
useEffect stops being confusing and becomes a powerful tool you can rely on daily.
Remember:
useEffect ≠ rendering
useEffect = logic that runs after rendering
useEffect connects React to external processes
useEffect replaces complex lifecycle methods
useEffect powers real-time, dynamic apps
Master useEffect, and React becomes much clearer, easier, and more enjoyable.
Because React wants pure rendering without side effects.
To control when the effect runs once, always, or based on specific values.
No. Only when you start processes like listeners or timers.
Yes. It's recommended to separate effects based on logic.
React Strict Mode intentionally double-invokes effects to detect issues.
No. Only use it for side effects not for every piece of logic.
No. Only for actions outside React's rendering cycle.