React JS
React fundamentals, hooks, state management, lifecycle, and advanced patterns
Questions14 shown
React is a JavaScript library built by Facebook for creating user interfaces. Think of it like a set of building blocks — you create small, reusable pieces called components, and then snap them together to build your entire app.
Here's why developers love it:
Component-Based — You break your UI into small, independent pieces. A button, a navbar, a card — each is its own component that you can reuse anywhere.
Virtual DOM — Instead of updating the real webpage directly (which is slow), React keeps a lightweight copy in memory. It figures out what changed, and only updates those specific parts. Super fast.
One-Way Data Flow — Data flows in one direction (parent to child), which makes your app predictable and easier to debug.
Huge Ecosystem — Thousands of libraries, tools, and a massive community to help you.
In simple terms, React makes building interactive UIs feel like assembling Lego blocks instead of writing everything from scratch.
JSX stands for JavaScript XML. It lets you write HTML-like code directly inside your JavaScript files.
const greeting = <h1>Hello, World!</h1>;Now, browsers don't understand JSX. Behind the scenes, a tool called Babel converts it into regular JavaScript:
const greeting = React.createElement('h1', null, 'Hello, World!');Why use JSX?
1. Readable — It looks like the final HTML, so you can visualize your UI just by reading the code.
2. Powerful — You can embed any JavaScript expression inside curly braces {}.
3. Safe — JSX automatically escapes values, which helps prevent XSS attacks.
const name = 'Ravish';
const element = <p>Welcome, {name.toUpperCase()}!</p>;Think of JSX as a friendly shortcut. Instead of writing complex createElement calls, you just write something that looks like HTML — and React handles the rest.
const element = <h1>Hello, {name}!</h1>;The Virtual DOM is React's secret weapon for speed. Let me explain with a simple analogy.
Imagine you're editing a document. Instead of erasing the whole page and rewriting it every time you fix a typo, you just change that one word. That's what the Virtual DOM does for your webpage.
How it works step by step:
1. When your app's data changes, React creates a new Virtual DOM tree (a lightweight JavaScript copy of the real page).
2. React compares ("diffs") the new tree with the previous one.
3. It figures out the minimum changes needed.
4. It applies only those changes to the real DOM.
This process is called Reconciliation.
State changes → New Virtual DOM created → Diff with old → Patch real DOMWhy not update the real DOM directly?
The real DOM is slow. Every time you touch it, the browser has to recalculate styles, layout, and repaint the screen. By batching and minimizing these updates, React keeps things buttery smooth.
In short: Virtual DOM = smart middleman that saves the browser from doing unnecessary work.
Props (short for "properties") are how you pass data from a parent component to a child component. Think of them like function arguments — you send information in, and the child uses it.
// Parent passes data
function App() {
return <UserCard name="Ravish" role="Developer" />;
}
// Child receives it via props
function UserCard({ name, role }) {
return (
<div>
<h2>{name}</h2>
<p>{role}</p>
</div>
);
}Key things to remember:
Props are read-only. A child component should never modify the props it receives.
Props flow one way — from parent to child (top to bottom).
You can pass anything as props: strings, numbers, arrays, objects, even other components.
There's a special prop called children that lets you pass content between opening and closing tags:
<Card>
<p>This becomes props.children</p>
</Card>Props are the backbone of communication in React. They keep your components flexible and reusable.
State is data that a component owns and manages itself. When state changes, React automatically re-renders the component to show the updated data.
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
);
}Props vs State — the key differences:
| Feature | Props | State |
|---------|-------|-------|
| Who controls it? | Parent component | The component itself |
| Can it change? | No (read-only) | Yes (via setter function) |
| Triggers re-render? | When parent re-renders | When state updates |
| Direction | Parent → Child | Internal to component |
A simple way to think about it:
Props = what someone tells you (you can't change it)
State = what you know and can change yourself
When state changes, React says: "Something changed! Let me update the screen." That's the magic of reactivity.
const [count, setCount] = useState(0);Hooks are special functions that let you use React features (like state and lifecycle) inside functional components. Before Hooks, you needed class components for all of that — and classes were confusing with this, bind, and lifecycle methods scattered everywhere.
The most common Hooks:
| Hook | Purpose |
|------|---------|
| useState | Add state to a component |
| useEffect | Run side effects (API calls, timers, etc.) |
| useContext | Access shared data without prop drilling |
| useRef | Reference a DOM element or persist a value |
| useMemo | Cache expensive calculations |
| useCallback | Cache function references |
| useReducer | Complex state logic (like Redux-lite) |
Why Hooks were introduced:
1. No more `this` confusion — functional components are just regular functions.
2. Reuse logic easily — create custom hooks to share behavior between components.
3. Cleaner code — related logic stays together instead of being split across lifecycle methods.
Rules of Hooks:
Only call Hooks at the top level (not inside loops or conditions).
Only call Hooks from React functions (components or custom hooks).
Hooks made React simpler, and now functional components with Hooks are the recommended way to write React.
useEffect is the Hook you use for side effects — things like fetching data, setting up subscriptions, or updating the document title. Basically anything that happens *outside* the render.
import { useEffect, useState } from 'react';
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
fetch(`/api/users/${userId}`)
.then(res => res.json())
.then(data => setUser(data));
// Cleanup function (optional)
return () => {
console.log('Cleaning up...');
};
}, [userId]); // Dependency array
return user ? <h1>{user.name}</h1> : <p>Loading...</p>;
}The dependency array controls *when* the effect runs:
| Dependency Array | When it runs |
|------------------|--------------|
| Not provided | After every render |
| [] (empty) | Only once after first render |
| [userId] | When userId changes |
The cleanup function:
Runs before the component unmounts.
Also runs before the effect re-runs (to clean up the previous effect).
Perfect for clearing timers, unsubscribing from events, or canceling API calls.
Common mistake: Forgetting to add variables to the dependency array leads to stale closures — your effect uses outdated values.
useEffect(() => {
// side effect here
return () => {
// cleanup here
};
}, [dependency]);This is all about who controls the form data — React or the browser.
Controlled Components — React is the boss. The input's value is stored in state, and every change goes through React:
function ControlledForm() {
const [name, setName] = useState('');
return (
<input
value={name}
onChange={(e) => setName(e.target.value)}
/>
);
}Uncontrolled Components — The browser is the boss. You use a ref to grab the value when you need it:
function UncontrolledForm() {
const inputRef = useRef(null);
const handleSubmit = () => {
alert(inputRef.current.value);
};
return <input ref={inputRef} />;
}| Feature | Controlled | Uncontrolled |
|---------|-----------|-------------|
| Data lives in | React state | The DOM |
| Updates via | onChange handler | Browser default |
| Access value | Anytime (from state) | On demand (via ref) |
| Validation | Instant, on every keystroke | Usually on submit |
| Recommended? | Yes, for most cases | For simple forms or file inputs |
Rule of thumb: Use controlled components. They give you full control over validation, formatting, and conditional logic.
**Prop drilling** is when you pass data through many layers of components that don't even need it — just to get it to a deeply nested child. It's messy. **Context API** solves this by creating a "sha...
Create a free account to unlock login-level content, or go premium for everything.
When you render a list in React, each item needs a unique **key** prop. Keys help React identify which items changed, were added, or were removed. [code block] **Why are keys important?** Without k...
Create a free account to unlock login-level content, or go premium for everything.
`React.memo` is a **higher-order component** that tells React: "Hey, only re-render this component if its props actually changed." By default, when a parent re-renders, *all* its children re-render t...
Create a free account to unlock login-level content, or go premium for everything.
Both are performance hooks that **cache things** between renders. The difference is *what* they cache. **`useMemo`** caches the **result** of a calculation: [code block] **`useCallback`** caches the...
Create a free account to unlock login-level content, or go premium for everything.
`useReducer` is like `useState`'s big brother. It's perfect when your state logic gets **complex** — multiple values that depend on each other, or state transitions that follow specific rules. [code ...
Create a free account to unlock login-level content, or go premium for everything.
"Lifting state up" means **moving shared state to the closest common parent** of the components that need it. Imagine two sibling components that both need the same piece of data. Since React data fl...
Create a free account to unlock login-level content, or go premium for everything.
Interview Preparation
PremiumHigh-signal questions that come up most in real interviews. These are the ones worth spending extra time on.
A **Higher-Order Component (HOC)** is a function that takes a component and returns a **new enhanced component**. It's a pattern for reusing component logic. Think of it like a wrapper that adds extr...
Create a free account to unlock login-level content, or go premium for everything.
A **custom hook** is simply a JavaScript function that starts with `use` and calls other hooks inside it. It lets you **extract and reuse stateful logic** across components. [code block] **Why custo...
Create a free account to unlock login-level content, or go premium for everything.
Every React component goes through three phases in its life. Understanding this helps you know *when* to run your code. **1. Mounting (Birth)** The component is created and added to the DOM. - Constr...
Create a free account to unlock login-level content, or go premium for everything.
React is a **single-page application** (SPA) — there's only one HTML page. **React Router** handles navigation by swapping components in and out based on the URL, without reloading the page. [code bl...
Create a free account to unlock login-level content, or go premium for everything.
**Prop drilling** is when you pass props through multiple layers of components that don't even need them, just to reach a deeply nested child. [code block] **Why it's a problem:** - Makes components...
Create a free account to unlock login-level content, or go premium for everything.
**Reconciliation** is React's algorithm for efficiently updating the DOM. When your state changes, React needs to figure out what changed and update only those parts. **How it works:** 1. State chan...
Create a free account to unlock login-level content, or go premium for everything.
**Error Boundaries** are React components that catch JavaScript errors in their child component tree and display a **fallback UI** instead of crashing the whole app. Think of them like a `try/catch` ...
Create a free account to unlock login-level content, or go premium for everything.
By default, React bundles all your code into one big JavaScript file. **Code splitting** breaks it into smaller chunks that load **on demand** — so users only download what they need. **React.lazy** ...
Create a free account to unlock login-level content, or go premium for everything.
**Client-Side Rendering (CSR)** — The browser downloads an empty HTML shell and JavaScript does all the work: [code block] **Server-Side Rendering (SSR)** — The server generates the full HTML and se...
Create a free account to unlock login-level content, or go premium for everything.
**Redux** is a state management library that stores your entire app's state in one central place called the **store**. **Core concepts:** 1. **Store** — Single source of truth for all state 2. **Act...
Create a free account to unlock login-level content, or go premium for everything.
Here are the most effective ways to make your React app faster: **1. Avoid unnecessary re-renders** [code block] **2. Code splitting** [code block] **3. Virtualize long lists** [code block] **4. D...
Create a free account to unlock login-level content, or go premium for everything.