- Virtual Dom
- React Fragment
- React Portals
- props and state
- Hooks -> useState,useRef useReducer useEffect
- useCallback, useMemo
- Redux
- How jwt works in React
- Routin in React
- The DOM (Document Object Model) is a tree-like structure that represents your HTML elements in the browser.
- Example:
<div>
<h1>Hello</h1>
<p>World</p>
</div>This is represented as a DOM tree in the browser.
- The DOM is powerful but slow to update, especially when you make frequent changes, because each update triggers layout recalculations, styling, and re-rendering.
- The Virtual DOM (VDOM) is a lightweight, in-memory copy of the actual DOM.
- Itโs just a JavaScript object that mirrors the real DOM structure.
- Instead of updating the real DOM directly, React updates this Virtual DOM first.
Hereโs the flow:
I. Initial Render:
- React builds a Virtual DOM tree based on your components.
- It then creates the real DOM from this Virtual DOM.
II. On State/Props Change:
- React rebuilds a new Virtual DOM for the updated UI.
- It then compares the new Virtual DOM with the previous one (this process is called diffing).
III. Reconciliation (Efficient Updates):
- React finds only the parts of the DOM that changed.
- It updates only those nodes in the real DOM, instead of re-rendering the entire page.
- Performance: Minimizes costly direct manipulations of the real DOM.
- Efficiency: Uses diffing + reconciliation to batch and optimize updates.
- Declarative UI: You just declare what the UI should look like, and React figures out how to update it efficiently.
โ In short: The Virtual DOM is a JavaScript representation of the real DOM that React uses to make UI updates efficient. React updates the Virtual DOM first, compares it with the old one, and then updates only the necessary parts of the real DOM.
A Fragment is a wrapper component in React (<React.Fragment> or shorthand <> </>) that lets you group multiple elements without adding extra nodes to the DOM.
React Fragments let you group multiple elements without adding an extra node to the DOM. Unlike a div, they donโt create unnecessary wrappers, keeping the DOM clean and avoiding layout/CSS issues. Use
<>
<h1>Title</h1>
<p>Description</p>
</>
React Portals let you render children into a DOM node outside the parent hierarchy, useful for modals, tooltips, and dropdowns, while still preserving Reactโs component structure.
A Portal lets you render a React componentโs children into a different place in the DOM tree than its parent component. You create one with:
ReactDOM.createPortal(child, container)child: JSX you want to render.container: The DOM node where it should be inserted.
- When you need a component visually outside its parent hierarchy but still want it to behave as part of the React component tree.
- Common use cases:
- Modals / Dialogs
- Tooltips
- Dropdowns / Popovers
- Floating UI elements
// index.html
<body>
<div id="root"></div>
<div id="modal-root"></div>
</body>// Modal.js
import ReactDOM from "react-dom";
function Modal({ children }) {
return ReactDOM.createPortal(
<div className="modal">{children}</div>,
document.getElementById("modal-root")
);
}<Modal>
<h2>This is a modal</h2>
</Modal>๐ Even if you call <Modal> inside your app, it renders inside #modal-root in the DOM.
-
Definition: Short for properties, props are used to pass data from parent to child components.
-
Characteristics:
- Immutable (read-only inside the child).
- Passed down from parent โ child.
- Makes components reusable.
Example:
function Greeting({ name }) {
return <h1>Hello, {name}!</h1>;
}
<Greeting name="Mousharraf" />-
Definition: State is local data storage managed within a component.
-
Characteristics:
- Mutable (can change over time).
- Managed internally by the component with
useState(orthis.statein class components). - When state changes โ component re-renders.
Example:
function Counter() {
const [count, setCount] = React.useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
);
}| Aspect | Props | State |
|---|---|---|
| Who owns it? | Parent (passed down) | Component itself |
| Mutable? | โ Immutable | โ Mutable |
| Usage | Pass data/config to child components | Store data that changes over time |
| Trigger Re-render? | No (unless parent re-renders) | Yes, when state changes |
โ In short (interview-ready):
- Props are inputs passed from parent to child, read-only.
- State is data managed inside a component, can change, and causes re-renders.
Do you want me to also give you a one-liner analogy (like a real-life example) so itโs easier to recall in an interview?
- Props flow parent โ child.
- But if you want the child to send data back to the parent, you pass a callback function as a prop.
So the data still flows down (the function is passed from parent to child), but the execution flows up (child calls the function โ parent receives data).
// Parent
function Parent() {
const [message, setMessage] = React.useState("");
const handleChildMessage = (data) => {
setMessage(data);
};
return (
<>
<Child sendMessage={handleChildMessage} />
<p>Message from child: {message}</p>
</>
);
}
// Child
function Child({ sendMessage }) {
return (
<button onClick={() => sendMessage("Hello Parent!")}>
Send Message
</button>
);
}๐ Here:
sendMessage(a function) is passed from parent โ child as a prop.- The child invokes it to pass data back to the parent.
Props are always passed from parent to child, but using callback props, a child can โnotifyโ or send data back to the parent.**
- โ Always call hooks at the top level of your component or custom hook.
- โ Donโt call them inside loops, conditions, or nested functions.
Why? React relies on the order of hooks being the same across renders. If you call them conditionally, React canโt track which state or effect corresponds to which hook.
Bad โ
if (isLoggedIn) {
const [user, setUser] = useState(null); // โ Wrong
}Good โ
const [user, setUser] = useState(null);
if (isLoggedIn) {
// use user here
}
### **2. Only Call Hooks from React Functions**
* โ
Call hooks from:
* React **functional components**
* Custom hooks (functions starting with `use`)
* โ Donโt call hooks from:
* Regular JavaScript functions
* Class components
* Outside of a component
**Bad โ**
```jsx
function fetchData() {
const [data, setData] = useState([]); // โ Not allowed here
}Good โ
function MyComponent() {
const [data, setData] = useState([]); // โ
Allowed inside React component
}- Custom Hooks must start with
use(e.g.,useAuth,useFetch) โ helps React enforce rules. - Use the
eslint-plugin-react-hookspackage (comes with Create React App) to catch violations. - Hooks must always be called in the same order across renders.
โ In short (interview-ready):
- Rule 1: Call hooks at the top level, never inside loops, conditions, or nested functions.
- Rule 2: Call hooks only in React function components or custom hooks, not in regular functions or classes.
- Used to store stateful data in a functional component.
- Re-renders the component whenever the state changes.
const [count, setCount] = useState(0);
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>โ Use when:
- You need UI updates when a value changes (e.g., form inputs, toggles, counters).
- Stores a mutable reference that doesnโt trigger a re-render when changed.
- Commonly used for DOM access or storing values across renders without causing updates.
const inputRef = useRef();
const focusInput = () => {
inputRef.current.focus(); // Access DOM directly
};
<input ref={inputRef} type="text" />
<button onClick={focusInput}>Focus Input</button>โ Use when:
- You need to persist values between renders without re-rendering.
- Example: DOM elements, timers, previous values.
- Alternative to
useStatefor more complex state logic. - Works like Redux: uses a reducer function with
stateandaction.
const reducer = (state, action) => {
switch (action.type) {
case 'increment': return { count: state.count + 1 };
case 'decrement': return { count: state.count - 1 };
default: return state;
}
};
const [state, dispatch] = useReducer(reducer, { count: 0 });
<button onClick={() => dispatch({ type: 'increment' })}>
Count: {state.count}
</button>โ Use when:
- State updates are complex (multiple sub-values, business logic).
- Example: Forms, wizards, authentication state.
- Runs side effects (code outside rendering).
- Examples: fetching data, subscriptions, event listeners.
useEffect(() => {
console.log("Component mounted or count changed");
return () => {
console.log("Cleanup on unmount or before re-run");
};
}, [count]); // Dependency arrayโ Use when:
- Interacting with APIs.
- Setting up subscriptions or timers.
- Running code when props/state change.
| Hook | Purpose | Re-render on change? | Example Use |
|---|---|---|---|
| useState | Manage stateful values | โ Yes | Counter, form input |
| useRef | Store mutable value / DOM ref | โ No | Focus input, save prev value |
| useReducer | Complex state logic (like Redux) | โ Yes | Multi-step forms, auth flow |
| useEffect | Side effects (API, events) | N/A | Fetch data, subscriptions |
Great question! useCallback and useMemo are performance optimization hooks in React. They are useful when you want to avoid unnecessary re-renders or expensive calculations. Letโs break them down.
-
Purpose: Memoizes a function, so that React doesnโt recreate it on every render.
-
When to use:
- Passing a function as a prop to a child component that is wrapped with
React.memo. - Avoids unnecessary re-renders of the child component when the parent re-renders.
- Passing a function as a prop to a child component that is wrapped with
Example:
import React, { useState, useCallback } from "react";
const Child = React.memo(({ onClick }) => {
console.log("Child re-rendered");
return <button onClick={onClick}>Click me</button>;
});
function Parent() {
const [count, setCount] = useState(0);
// Without useCallback, this function is recreated on every render
const handleClick = useCallback(() => {
setCount(prev => prev + 1);
}, []); // Empty dependency: memoized once
return (
<div>
<p>Count: {count}</p>
<Child onClick={handleClick} />
</div>
);
}โ
Benefit: Child will only re-render when handleClick changes (here it doesnโt, thanks to useCallback).
-
Purpose: Memoizes a computed value so React doesnโt recalculate it on every render.
-
When to use:
- Expensive calculations that donโt need to run on every render.
- Dependent on certain values (dependencies).
Example:
import React, { useState, useMemo } from "react";
function ExpensiveComponent({ num }) {
const factorial = useMemo(() => {
console.log("Calculating factorial...");
let result = 1;
for (let i = 1; i <= num; i++) {
result *= i;
}
return result;
}, [num]); // Recalculate only when `num` changes
return <p>Factorial of {num} is {factorial}</p>;
}
function App() {
const [count, setCount] = useState(1);
return (
<div>
<ExpensiveComponent num={count} />
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}โ
Benefit: The factorial calculation only runs when num changes, saving performance on other re-renders.
| Hook | Memoizes | Use Case |
|---|---|---|
| useCallback | Function | Pass stable functions to children to prevent unnecessary re-renders |
| useMemo | Value / Computation | Avoid expensive calculations on every render |
๐ก Rule of thumb:
- Use these only when performance issues appear, because overusing them can make the code more complex.
If you want, I can also give a visual diagram showing how
useState,useCallback, anduseMemointeract during re-renders, which makes it super easy to remember.
Do you want me to do that?