Study material
Reactjs
Attachments(1)
Core Concepts and Architecture
The foundation of React involves understanding how it interacts with the Document Object Model (DOM), handles component rendering, and maintains structural integrity during development.
The Virtual DOM
The Virtual DOM is a lightweight, in-memory representation of the actual HTML DOM. React uses this abstraction to optimize rendering performance. Instead of updating the real DOM immediately when state changes, React updates the Virtual DOM first. It then compares the new Virtual DOM with a snapshot of the previous one (a process called reconciliation or diffing). Finally, it calculates the most efficient way to update the real DOM and applies only those specific changes.
A common misconception is that the Virtual DOM directly updates the real DOM faster. In reality, real DOM manipulation is always slow. The Virtual DOM is faster because it minimizes direct manipulations by batching updates and applying them simultaneously.
By default, standard tree edit distance algorithms operate in time complexity. React implements a heuristic algorithm based on assumptions about element types and keys.
React Fragments and Strict Mode
React.Fragment: Returning multiple sibling elements from a component normally requires wrapping them in a parent element (like a<div>). This can pollute the DOM tree and break CSS grid or flexbox layouts. Fragments (<React.Fragment>or the shorthand<></>) allow returning multiple elements without adding extraneous nodes to the DOM.- React Strict Mode: A development-only wrapper (
<React.StrictMode>) that intentionally renders components twice. This duplicate rendering helps identify side effects, deprecated lifecycle methods, and unsafe state mutations that might cause bugs in production.
Summary: The Virtual DOM optimizes updates via batching, Fragments keep the DOM tree clean, and Strict Mode enforces pure functions in development.
Self-Check: Why does Strict Mode render components twice, and does this affect the production build?
Components, Props, and Data Flow
React applications are built from isolated pieces of UI called components, which pass data downward using properties.
Immutability of Props
Props (properties) are the mechanism for passing data from parent to child components. A strict rule in React is that a component must never modify its own props. Components must act as pure functions with respect to their props. If a component needs to alter data based on a prop, it must do so by managing its own local state or by invoking a callback function passed down from the parent.
Prop Drilling
Prop Drilling is the process of passing props through multiple intermediate nested components that do not need the data themselves, purely to reach a deeply nested child component that does.
Note: Context API or state management libraries are typically used to resolve severe prop drilling.
Conditional Rendering and HTML Injection
- Conditional Rendering: React relies on standard JavaScript operators to render UI conditionally inline. The recommended approaches are the ternary operator (
condition ? <ComponentA/> : <ComponentB/>) and the logical AND operator (condition && <Component/>). - HTML Injection: Injecting raw HTML strings directly into the DOM is handled via the
dangerouslySetInnerHTMLattribute. The verbose and intimidating name acts as a semantic warning that this practice exposes the application to Cross-Site Scripting (XSS) attacks.
Summary: Data flows top-down via immutable props, inline conditional logic dictates rendering, and direct HTML injection is explicitly flagged as hazardous.
Self-Check: How does the ternary operator differ structurally from the logical AND operator in JSX rendering?
State Management and Forms
State dictates the interactive portions of a React application. Handling user input requires bridging standard HTML behavior with React's state management.
Controlled Components
In a standard HTML form, elements like <input>, <textarea>, and <select> maintain their own internal state. In a Controlled Component, the form data is exclusively controlled by the React state. The component dictates the value of the input, and state updates occur via an onChange handler.
// Worked Example: Controlled Component
const NameForm = () => {
const [name, setName] = useState("");
const handleChange = (event) => {
setName(event.target.value); // State dictates input value
};
return <input type="text" value={name} onChange={handleChange} />;
};
Asynchronous State Updates
When a state setter function (e.g., from useState) is invoked, the state does not update immediately on the next line of code. React groups (batches) multiple state updates together into a single render pass to optimize performance and prevent unnecessary re-renders.
Developers often attempt to
console.log()a state variable immediately after calling its setter function and become confused when the old value is printed. The state value is only guaranteed to be updated on the next render cycle.
Summary: Controlled components synchronize form inputs with React state, while state updates are batched asynchronously for optimal performance.
Self-Check: If a state setter is called three times synchronously in the same function, how many re-renders will React trigger?
React Hooks
Hooks allow functional components to "hook into" React state and lifecycle features.
Rules of Hooks
To ensure predictability, React enforces strict rules:
- Top Level Only: Hooks must be called at the top level of the component. They cannot be placed inside loops, conditions, or nested functions. This guarantees that Hooks are executed in the exact same order every time a component renders.
- React Functions Only: Hooks can only be called from functional React components or custom hooks, never from standard JavaScript functions or class components.
The useEffect Hook
The useEffect hook manages side effects (data fetching, subscriptions, manual DOM manipulation). It accepts two arguments: a setup function and an optional dependency array.
| Dependency Array Status | Execution Behavior |
|---|---|
| Omitted completely | Effect runs after the initial mount and after every single re-render. |
**Empty array []** | Effect runs only once after the initial mount. |
**Array with values [x, y]** | Effect runs after initial mount and whenever x or y change. |
Cleanup Phase: If the effect returns a function, React treats this as a cleanup mechanism. This returned function mimics componentWillUnmount. It executes immediately before the component unmounts, or before the effect re-runs due to a dependency change.
The useRef Hook
While often used to directly reference DOM elements, useRef is fundamentally used to store a mutable value that does not trigger a re-render when updated. It returns an object with a single property: .current. Modifying .current happens synchronously and silently, making it ideal for storing interval IDs, previous state values, or rendering flags.
Summary: Hooks must execute in a consistent order at the top level; useEffect handles side effects and cleanups based on dependency arrays, while useRef holds mutable data without triggering renders.
Self-Check: Why does placing a hook inside an if statement violate React's internal tracking mechanism?
Performance Optimization
As applications grow, preventing unnecessary calculation and rendering becomes critical.
useMemo vs useCallback
Both hooks prevent unnecessary work during re-renders, but they memoize different things:
useMemo: Memoizes a computed value. It executes a provided function and caches the result. It only recalculates the value when its dependencies change. Used for computationally expensive operations (e.g., sorting large arrays).useCallback: Memoizes a function definition. It caches the function instance itself so that the exact same function reference is passed across renders. Used primarily when passing callbacks as props to optimized child components.
Mnemonic: useMemo returns the Menu (the final product/value). useCallback returns the Cook (the function itself).
React.memo
While hooks optimize internal logic, React.memo optimizes component rendering. It is a Higher-Order Component (HOC) that wraps a functional component. It memoizes the entire component, skipping re-renders if the incoming props remain strictly identical to the previous render.
Summary: useMemo caches values, useCallback caches functions, and React.memo caches entire component renders based on prop equality.
Self-Check: If a parent component creates a new object inline and passes it as a prop to a child wrapped in React.memo, will the child re-render?
Advanced Patterns and Ecosystem
Handling edge cases, global data, and large bundle sizes requires advanced architectural patterns.
Context API
The Context API solves the problem of prop drilling. It allows global data—such as UI themes, localization languages, or user authentication status—to be shared directly with any component in the tree, regardless of depth, without passing props manually at every level.
Portals and Error Boundaries
-
Portals (
ReactDOM.createPortal): Renders a child element into a DOM node that exists entirely outside the current component's DOM hierarchy. -
Real-world application: Modals, tooltips, and floating menus. Portals prevent CSS properties like
overflow: hiddenorz-indexon parent containers from clipping or hiding the overlay. -
Error Boundaries: specialized Class components designed to catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of crashing the whole application.
-
static getDerivedStateFromError: Used to update state and render a fallback UI. -
componentDidCatch: Used to log the error information to an external monitoring service.
Higher-Order Components (HOC)
A Higher-Order Component (HOC) is a pattern for reusing component logic. Conceptually, a HOC is a function that takes a component as an argument and returns a new, enhanced component. It injects additional props or behaviors (e.g., withRouter or connect in Redux).
Lazy Loading and Suspense
To reduce initial load times, React supports dynamically importing components only when they are needed.
React.lazy: Wraps dynamic imports to facilitate lazy loading.<Suspense>: A component that wraps the lazy-loaded components. It utilizes afallbackprop (such as a<Spinner/>) to display temporary content while the requested component chunk is being downloaded over the network.
Summary: Context circumvents prop drilling, Portals break out of CSS hierarchies, Error Boundaries prevent catastrophic crashes, HOCs share structural logic, and Suspense provides graceful loading states.
Self-Check: Can a functional component be an Error Boundary using hooks, or is a Class component strictly required?