React Interview Questions A-Z

Components (Class, Functional)

Back to Top
What are the differences between class and functional components?

Class Components: These are written using JavaScript classes. They have their own state and can use lifecycle methods like componentDidMount. They use the 'this' keyword to access props and state.

Functional Components: These are written as regular JavaScript functions. They are simpler and easier to read. With React Hooks, they can now have state and lifecycle features too.

Key differences:

  • Class components use 'this' keyword, functional components don't
  • Class components have built-in lifecycle methods, functional components use hooks
  • Functional components are shorter and easier to test
  • Both can have state now thanks to hooks

Pure Component

Back to Top
What is a PureComponent and when should you use it?

A PureComponent is a special type of component that automatically checks if it needs to re-render. It compares the old props and state with the new ones. If they're the same, it skips re-rendering to improve performance.

When to use PureComponent:

  • When your component renders the same output for the same props and state
  • When you want to improve performance by reducing unnecessary re-renders
  • When your data is simple (numbers, strings, booleans)

When to avoid PureComponent:

  • When your props contain complex objects or arrays
  • When you need custom logic to decide when to re-render

Hooks

Back to Top
What are React Hooks and why were they introduced?

React Hooks are special functions that let you use React features in functional components. They let you "hook into" React's state and lifecycle features without writing a class.

Why hooks were created:

  • To share logic between components more easily
  • To make components simpler and easier to understand
  • To avoid the complexity of class components
  • To group related logic together

Common hooks:

  • useState: For managing state in functional components
  • useEffect: For side effects like API calls or setting up subscriptions
  • useContext: For accessing context values
  • useRef: For accessing DOM elements or storing mutable values

DOM and Virtual DOM

Back to Top
What is the Virtual DOM and how does it work?

DOM (Document Object Model): This is the actual structure of your webpage that the browser displays. Changing it directly can be slow.

Virtual DOM: This is React's copy of the DOM kept in memory. It's much faster to work with than the real DOM.

How it works:

  1. When something changes, React creates a new Virtual DOM tree
  2. React compares this new tree with the previous Virtual DOM tree
  3. React finds what actually changed (this is called "diffing")
  4. React updates only the parts of the real DOM that changed

Benefits:

  • Much faster than updating the real DOM directly
  • Makes React apps feel smooth and responsive
  • Reduces the number of expensive DOM operations

Controlled and Uncontrolled Components

Back to Top
What are controlled and uncontrolled components?

Controlled Components: React controls the form input values. The input value is stored in React state, and you update it through React.

Uncontrolled Components: The browser controls the form input values. You use refs to get the values when you need them.

When to use controlled:

  • When you need to validate input as the user types
  • When you want to disable submit button based on input
  • When you need to format the input (like phone numbers)
  • When multiple inputs depend on each other

When to use uncontrolled:

  • For simple forms where you just need the final value
  • When integrating with non-React libraries
  • For file uploads (always uncontrolled)

Higher Order Components (HOC)

Back to Top
What are Higher Order Components?

A Higher-Order Component (HOC) is a function that takes a component and returns a new component with extra features. It's like a wrapper that adds functionality.

What HOCs do:

  • Add extra props to a component
  • Handle authentication or permissions
  • Add loading states or error handling
  • Connect components to external data sources

Common examples:

  • withAuth: Checks if user is logged in before showing component
  • withLoading: Shows loading spinner while data is fetching
  • withErrorHandling: Catches and displays errors

Modern alternative: Custom hooks are now preferred over HOCs because they're simpler and don't create wrapper components.

React Fragment

Back to Top
What is React Fragment and why use it?

React Fragment lets you group multiple elements together without adding an extra div to the DOM. It's like an invisible wrapper.

Why use Fragment:

  • Keeps your HTML clean without unnecessary wrapper divs
  • Prevents CSS layout issues caused by extra containers
  • Slightly better performance (fewer DOM nodes)
  • More semantic HTML structure

Two ways to write Fragment:

  • Long form: React.Fragment
  • Short form: Empty tags like <> and </>

When you need Fragment:

  • When a component needs to return multiple elements
  • When mapping over arrays and each item has multiple elements
  • When you want to avoid wrapper divs that break your CSS

Lazy Loading

Back to Top
What is lazy loading in React?

Lazy loading in React is a performance optimization technique where components (or parts of your application) are loaded only when they are needed, instead of loading everything upfront when the application starts. This helps reduce the initial bundle size, improves page load times, and provides a smoother user experience, especially for large applications.

const MyComponent = React.lazy(() => import("./MyComponent"));

How it works:

  • Components are split into separate files
  • React loads them only when user navigates to that part
  • Shows a loading message while the component downloads

Benefits:

  • Faster initial page load
  • Smaller bundle size for each page
  • Better user experience
  • Saves bandwidth for users

What you need:

  • React.lazy(): To mark a component as lazy
  • Suspense: To show loading state while component loads
  • Dynamic imports: To split the code

Best for: Different pages/routes, large components, features not immediately visible

                                
import React, { Suspense } from "react";
const MyComponent = React.lazy(() => import("./MyComponent"));

function App() {
  return (
    <div>
      <h1>Lazy Loading Example</h1>
      <Suspense fallback={<p>Loading...</p>}>
        <MyComponent />
      </Suspense>
    </div>
  );
}
                                
                            

Stateless and Stateful Components

Back to Top
What are stateless and stateful components?

Stateless Components: These don't have their own state. They just receive props and display them. They're like pure functions - same input always gives same output.

Stateful Components: These have their own state that can change over time. They can remember things and update themselves.

Stateless characteristics:

  • No internal state or memory
  • Only depend on props passed to them
  • Easier to test and understand
  • More reusable

Stateful characteristics:

  • Have internal state that changes
  • Can trigger re-renders when state updates
  • Handle user interactions and data changes
  • More complex but more powerful

When to use each:

  • Stateless: For displaying data, simple UI components
  • Stateful: For forms, counters, data that changes over time

Pointer Events

Back to Top
How do you handle pointer events in React?

Pointer events are a modern way to handle mouse, touch, and pen input all in one. React provides synthetic pointer events that work the same across all devices.

Common pointer events: onPointerDown (when you press), onPointerUp (when you release), onPointerMove (when you move), onPointerEnter (when you enter an area), onPointerLeave (when you exit an area).

Benefits: Works with mouse, touch, and stylus. Better than separate mouse and touch events.

Key Props

Back to Top
What are keys in React and why are they important?

Keys are special props that help React identify which items have changed in a list. Think of them like ID tags for list items.

Why keys matter: They help React update lists efficiently. Without keys, React might re-render the entire list when just one item changes.

Good keys: Use unique, stable IDs like database IDs. Bad keys: Don't use array indexes (can cause bugs when list order changes).

Rule: Each key should be unique among siblings, but can repeat in different lists.

Inline Conditional Rendering

Back to Top
How do you conditionally render elements in React?

Conditional Rendering: It means deciding which UI to show depending on certain conditions (e.g., if a user is logged in or not).

Methods:

  • Ternary operator: {condition ? showThis : showThat}
  • Logical AND (&&): {condition && showThis}
  • If/else statements: Write conditions above return and decide what to render.

Example in React:


function App() {
    const isLoggedIn = true;

    return (
        <div>
        {/* Ternary operator */}
        <div>
            {isLoggedIn ? <h2>Welcome Back!</h2> : <h2>Please Login</h2>}
        </div>

        {/* Logical AND */}
        <div>
            {isLoggedIn && <button>Logout</button>}
        </div>
        </div>
    );
}
                        

JSX (JavaScript XML)

Back to Top
What is JSX and how does it work?

JSX is a syntax that lets you write HTML-like code inside JavaScript. It makes React components easier to read and write.

How it works: JSX gets converted into regular JavaScript function calls that create React elements.

Rules: Use className instead of class, close all tags, wrap multiple elements in one parent, use curly braces for JavaScript expressions.

Benefits: More readable than pure JavaScript, familiar HTML syntax, better error messages, good tooling support.

React Router

Back to Top
How does routing work in React applications?

React applications are Single Page Applications (SPA). Instead of loading a new page from the server for every navigation, React Router updates the UI dynamically using the browser’s History API (pushState, replaceState, popstate). This allows smooth navigation without full page reloads.

Key Concepts:

  • BrowserRouter / HashRouter: Defines the type of routing (normal history vs. hash-based for static hosting).
  • Routes: Maps a URL path to a React component.
  • Link: Navigates between pages without reloading the app.
  • useNavigate: Navigate programmatically (e.g., after login).
  • useParams: Access dynamic route values like /user/123.
  • useSearchParams: Access query string values (e.g., ?filter=active).
  • Nested Routes: Define routes inside routes, e.g., /dashboard/profile.
  • Protected Routes: Restrict access to authenticated users only.

Example:


<BrowserRouter>
    <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/user/:id" element={<User />} />
    </Routes>
</BrowserRouter>
                        

Benefits:

  • Fast navigation without full page reloads
  • Works with browser back/forward buttons
  • Allows bookmarking and sharing deep links
  • Supports nested and dynamic routes
  • Enables authentication-based protected pages

In short: React Router turns your single-page React app into a multi-view experience, making navigation smooth, efficient, and user-friendly.

createElement and cloneElement

Back to Top
What are createElement and cloneElement?

React.createElement: It’s a fundamental method in React used to create React elements. React elements are the building blocks of a React app, representing what should appear on the screen. React uses them in its virtual DOM to efficiently update and render the UI.

React.cloneElement: A method to copy an existing React element and optionally add or override props. Useful when you want to modify a child element without rewriting it.

In short:

  • createElement → Creates elements from JSX (React uses this internally).
  • cloneElement → Copies an element and adds new props.

Example in React:


// Using createElement (JSX is converted to this)
const element1 = React.createElement('h1', null, 'Hello World');

// Equivalent JSX
const element2 = <h1>Hello World</h1>;

// Using cloneElement to add props
function Wrapper({ children }) {
    return React.cloneElement(children, { style: { color: 'blue' } });
}

function App() {
    return (
        <Wrapper>
        <h2>This text will be blue</h2>
        </Wrapper>
    );
}
                        

Children Prop

Back to Top
What is the children prop in React?

Definition: The children prop contains whatever you place between the opening and closing tags of a component. Think of it as a special slot where content can be inserted.

Why it's useful: Makes components more flexible and reusable. You can create wrapper components like Card, Modal, or Button that can hold different content.

Types of children: Can be text, React elements, other components, or even functions. React also provides React.Children utilities to handle children safely.

Example:


function Card({ children }) {
    return (
        <div className="card">
            <div className="card-body">
                {children}
            </div>
        </div>
    );
}

// Usage
function App() {
    return (
        <Card>
            <h2>Hello World</h2>
            <p>This is a card content.</p>
        </Card>
    );
}
                        

JavaScript Prototype

Back to Top
How do prototypes work in JavaScript and React?

Prototype is JavaScript's way of sharing properties and methods between objects. Every JavaScript object has a prototype - it's like a blueprint that objects inherit from.

How it works: When you try to access a property on an object, JavaScript first looks on the object itself. If not found, it looks up the prototype chain.

In React context:

  • Class components inherit from React.Component through prototypes
  • Methods like render() and lifecycle methods come from the prototype chain
  • Functional components don't use prototypes (they're just functions)

Modern relevance: While prototypes are fundamental to JavaScript, React has moved toward functional components and hooks, reducing direct prototype usage.

Reconciliation

Back to Top
What is reconciliation in React?

Definition: Reconciliation is React’s process of updating the UI efficiently by comparing the new Virtual DOM with the previous one and applying only the necessary changes to the real DOM.

How it works: React performs a “diffing” algorithm on the Virtual DOM to detect what has changed, and updates only those parts of the DOM that actually need to change.

Key factors React checks:

  • Element type (e.g., <div> vs <span>)
  • Keys in lists (to match elements correctly)
  • Props and state changes

Why it matters: Efficient updates improve performance, reduce unnecessary re-rendering, and make React applications faster.

Example:


function App() {
    const [count, setCount] = React.useState(0);

    return (
        <div>
            <h1>Count: {count}</h1>
            <button onClick={() => setCount(count + 1)}>Increment</button>
        </div>
    );
}

// When 'count' changes, React updates only the <h1> text, not the entire DOM.
                        

React Portals

Back to Top
What are React Portals?

Definition: React Portals allow you to render a component's children into a DOM node that exists outside the DOM hierarchy of its parent component. Essentially, it lets you “teleport” part of your UI to a different place in the DOM.

Common Use Cases:

  • Modals and dialogs
  • Tooltips and popovers
  • Dropdown menus
  • Notifications or toasts

How it works: Even though the DOM elements are rendered elsewhere, the portal component remains part of the React component tree. This means React still manages its state, context, and event propagation as usual.

Benefits:

  • Avoids CSS z-index and overflow issues by rendering outside parent containers.
  • Maintains React’s event system and state management.
  • Keeps components reusable and modular without worrying about DOM hierarchy.

Example:


import React from 'react';
import ReactDOM from 'react-dom';

function Modal({ children }) {
    return ReactDOM.createPortal(
        <div className="modal">
            {children}
        </div>,
        document.getElementById('modal-root') // renders outside parent DOM
    );
}

function App() {
    return (
        <div>
            <h1>Main App Content</h1>
            <Modal>
                <p>This is a modal rendered using a portal.</p>
            </Modal>
        </div>
    );
}
                        

Server-Side Rendering (SSR)

Back to Top
What is Server-Side Rendering?

Definition: Server-Side Rendering (SSR) is the process of generating the HTML of a React application on the server and sending it to the browser fully rendered, instead of letting the client build the HTML with JavaScript.

Benefits:

  • Faster initial page load (users see content sooner).
  • Better SEO because search engines can crawl HTML directly.
  • Improved performance on slow devices or browsers.

Challenges:

  • More complex setup compared to client-side rendering.
  • Server must handle React rendering for every request.
  • Can be slower for interactive features that rely heavily on client-side JavaScript.

Popular tools/frameworks: Next.js (most popular), Gatsby, Remix — they simplify SSR implementation.

Example using Next.js:


// pages/index.js
export default function Home({ posts }) {
    return (
        <div>
            <h1>Blog Posts</h1>
            <ul>
                {posts.map(post => (
                    <li key={post.id}>{post.title}</li>
                ))}
            </ul>
        </div>
    );
}

// This function runs on the server

export async function getServerSideProps() {
    const res = await fetch('https://api.example.com/posts');
    const posts = await res.json();

    return { props: { posts } };
}
                        

Redux

Back to Top
What is Redux and how does it work?

Redux is a predictable state container library for JavaScript applications that provides a centralized store to manage the entire application's state, making state changes predictable and easy to track. It is used in larger applications to simplify state management, especially when data needs to be shared across many components. It follows the principle of unidirectional data flow.

Key Concepts:

  • Store: A single object that holds all application state.
  • Action: A plain JavaScript object that describes an event (e.g., { type: "ADD_TODO", payload: "Learn Redux" }).
  • Reducer: A pure function that takes the current state and an action, then returns the new state.
  • Dispatch: The method used to send actions to the store.
  • Subscriber: Components listen for store updates and re-render automatically when data changes.

How Redux Works (Flow):

User → Dispatch(Action) → Reducer → New State → UI Updates

Steps to Use Redux (with Example):

  1. Install Redux & React-Redux:
    npm install redux react-redux
  2. Create an Action:
    
    // actions.js
    export const addTodo = (task) => ({
        type: "ADD_TODO",
        payload: task
    });
                                    
  3. Create a Reducer:
    
    // reducers.js
    const initialState = [];
    
    export function todoReducer(state = initialState, action) {
        switch (action.type) {
            case "ADD_TODO":
                return [...state, action.payload];
            default:
                return state;
        }
    }
                                    
  4. Create a Store:
    
    // store.js
    import { createStore } from "redux";
    import { todoReducer } from "./reducers";
    
    const store = createStore(todoReducer);
    export default store;
                            
  5. Provide Store to React App:
    
    // index.js
    import React from "react";
    import ReactDOM from "react-dom";
    import { Provider } from "react-redux";
    import App from "./App";
    import store from "./store";
    
    ReactDOM.render(
        <Provider store={store}>
            <App />
        </Provider>,
        document.getElementById("root")
    );
                                    
  6. Use Redux in Components:
    
    // App.js
    import React from "react";
    import { useSelector, useDispatch } from "react-redux";
    import { addTodo } from "./actions";
    
    function App() {
        const todos = useSelector(state => state);
        const dispatch = useDispatch();
    
        return (
            <div>
                <h3>Todo List</h3>
                <button onClick={() => dispatch(addTodo("Learn Redux"))}>
                    Add Todo
                </button>
                <ul>
                    {todos.map((t, i) => <li key={i}>{t}</li>)}
                </ul>
            </div>
        );
    }
    
    export default App;
                                    

When to Use Redux:

  • Large applications with complex state management
  • When multiple components need access to the same data
  • When debugging, logging, or time-travel debugging is required

Modern Alternatives:

  • React Context + useReducer: Good for small/medium apps
  • Redux Toolkit (RTK): Modern way to use Redux with less boilerplate
  • Zustand, Recoil, Jotai: Other state management libraries with simpler APIs

In short: Redux provides a predictable way to manage state by centralizing it in one store and ensuring a strict one-way data flow. This improves maintainability, scalability, and debugging in large applications.

Redux connect()

Back to Top
What is connect() in Redux?

The connect() function is a higher-order component (HOC) from react-redux that connects React components to the Redux store. It was the traditional way of using Redux before useSelector and useDispatch hooks.

Example:


// Counter.js
import React from "react";
import { connect } from "react-redux";

function Counter({ count, dispatch }) {
    return (
        <div>
            <h3>Count: {count}</h3>
            <button onClick={() => dispatch({ type: "INCREMENT" })}>+</button>
        </div>
    );
}

const mapStateToProps = (state) => ({
    count: state.count
});

export default connect(mapStateToProps)(Counter);
                        

Modern Alternative: Prefer useSelector and useDispatch hooks.

Redux Thunk

Back to Top
What is Redux Thunk?

Redux Thunk is a middleware that allows writing asynchronous logic in Redux. Without it, Redux only supports synchronous state updates.

Example:


// actions.js
export const fetchUsers = () => {
    return async (dispatch) => {
        dispatch({ type: "USERS_REQUEST" });
        try {
            const res = await fetch("https://jsonplaceholder.typicode.com/users");
            const data = await res.json();
            dispatch({ type: "USERS_SUCCESS", payload: data });
        } catch (err) {
            dispatch({ type: "USERS_FAILURE", error: err });
        }
    };
};
                        

When to Use: API calls, async workflows, conditional logic.

Redux Saga

Back to Top
What is Redux Saga?

Redux Saga is a middleware that handles asynchronous side effects using generator functions. It provides a more powerful way to manage complex async workflows compared to Redux Thunk.

Example:


// sagas.js
import { call, put, takeEvery } from "redux-saga/effects";

function* fetchUsers() {
    try {
        const res = yield call(fetch, "https://jsonplaceholder.typicode.com/users");
        const data = yield res.json();
        yield put({ type: "USERS_SUCCESS", payload: data });
    } catch (err) {
        yield put({ type: "USERS_FAILURE", error: err });
    }
}

export function* watchUserRequests() {
    yield takeEvery("USERS_REQUEST", fetchUsers);
}
                        

When to Use: Complex async logic, race conditions, background tasks.

Redux Slice (RTK)

Back to Top
What is a Redux Slice?

In Redux Toolkit (RTK), a slice represents a portion of the Redux store with its reducer logic and actions bundled together using createSlice.

Example:


// todoSlice.js
import { createSlice } from "@reduxjs/toolkit";

const todoSlice = createSlice({
    name: "todos",
    initialState: [],
    reducers: {
        addTodo: (state, action) => {
            state.push(action.payload);
        },
        removeTodo: (state, action) => {
            return state.filter((_, i) => i !== action.payload);
        }
    }
});

export const { addTodo, removeTodo } = todoSlice.actions;
export default todoSlice.reducer;
                        

Benefits: Less boilerplate, easier to scale, built-in immutability with Immer.

Windowing (Virtualization)

Back to Top
What is windowing in React?

Windowing (or virtualization) means only rendering the items that are currently visible on screen, not the entire list. It's like having a window that shows only part of a huge list.

Why it's needed: Rendering thousands of items at once can make your app slow and use too much memory.

How it works: As you scroll, items outside the visible area are removed from the DOM and new ones are added.

Popular libraries: react-window (lightweight), react-virtualized (feature-rich). These handle the complex calculations for you.

When to use: Lists with hundreds or thousands of items, data tables, infinite scroll feeds.

Flux Architecture

Back to Top
What is Flux architecture?

Flux is a pattern for managing data flow in applications. It enforces a one-way data flow, making apps more predictable and easier to debug.

Four main parts:

  • Actions: Describe what happened (like "user clicked button")
  • Dispatcher: Central hub that receives actions and sends them to stores
  • Stores: Hold application state and logic
  • Views: React components that display data and trigger actions

Key rule: Data flows in one direction: Actions → Dispatcher → Stores → Views.

Legacy note: Flux was mostly replaced by Redux, which simplified the pattern.

Flux vs Redux

Back to Top
What's the difference between Flux and Redux?

Flux: The original pattern with multiple stores, a dispatcher, and more boilerplate code. More complex but flexible.

Redux: Simplified version of Flux with one store, no dispatcher, and pure functions (reducers) for updates.

Key differences:

  • Stores: Flux has many stores, Redux has one
  • Dispatcher: Flux needs one, Redux doesn't
  • Immutability: Redux enforces it, Flux doesn't require it
  • DevTools: Redux has better debugging tools

Result: Redux became more popular due to its simplicity and excellent developer experience.

Prop Drilling

Back to Top
What is prop drilling and how to avoid it?

Prop drilling happens when you pass props through many component layers just to get data to a deeply nested component. It's like passing a message through many people.

Problems: Makes components messy, harder to maintain, and couples components that shouldn't be connected.

Solutions:

  • Context API: Share data without passing props down
  • Component composition: Structure components differently
  • State management: Use Redux, Zustand, or other libraries
  • Custom hooks: Encapsulate data fetching logic

When it's okay: For 2-3 component levels, prop drilling is fine and actually clearer than alternatives.

useLayoutEffect

Back to Top
What is useLayoutEffect and when to use it?

useLayoutEffect is like useEffect, but it runs before the browser paints the screen. It's useful when you need to make DOM changes that users shouldn't see.

Difference from useEffect: useLayoutEffect runs synchronously before painting, useEffect runs after painting.

When to use useLayoutEffect:

  • Measuring DOM elements (getting sizes, positions)
  • Making visual changes that should appear instantly
  • Preventing visual flicker
  • Synchronizing with third-party DOM libraries

Warning: Can hurt performance if overused because it blocks painting. Prefer useEffect unless you specifically need synchronous execution.

Component Lifecycles

Back to Top
What are React component lifecycle methods?

React Component Lifecycle refers to the series of events (mounting, updating, unmounting) that happen from the creation of a component to its removal from the DOM. Lifecycle methods (in class components) or hooks (in functional components) allow developers to run code at specific points in this process.

Main Lifecycle Phases:

  • Mounting: Component is created and inserted into the DOM. (Runs once when the component is first rendered.)
  • Updating: Component re-renders when its props or state change.
  • Unmounting: Component is removed from the DOM.

Class Component Lifecycle Methods:

  • constructor() → Initialization (state, bindings)
  • componentDidMount() → Runs after first render (good for API calls, subscriptions)
  • shouldComponentUpdate() → Controls whether re-render should happen
  • componentDidUpdate(prevProps, prevState) → Runs after every update (good for reacting to changes)
  • componentWillUnmount() → Cleanup (remove listeners, cancel requests)

Functional Component Lifecycle (using Hooks):

In functional components, useEffect hook is used to handle all lifecycle phases.


// Mounting (componentDidMount)
useEffect(() => {
    console.log("Mounted");
}, []);

// Updating (componentDidUpdate)
useEffect(() => {
    console.log("Updated when count changes");
}, [count]);

// Unmounting (componentWillUnmount)
useEffect(() => {
    const id = setInterval(() => console.log("Running..."), 1000);
    return () => clearInterval(id); // cleanup
}, []);
                        

Summary:

  • Class Components: Use lifecycle methods (more verbose).
  • Functional Components: Use hooks (useEffect, useLayoutEffect) for all lifecycle needs.

Modern React Best Practice: Prefer functional components with hooks since they are cleaner, easier to reuse, and encouraged in React’s latest guidelines.

Data Flow

Back to Top
How does data flow work in React?

React uses one-way data flow (also called unidirectional data flow). Data flows down from parent to child components through props, like water flowing downhill.

Key principles:

  • Data flows down through props
  • Events flow up through callbacks
  • Child components can't directly change parent data
  • Makes apps predictable and easier to debug

Communication patterns: Parent to child (props), child to parent (callback functions), sibling to sibling (lift state up to common parent).

Benefits: Easier to understand, fewer bugs, better performance optimizations possible.

Styling in React

Back to Top
What are the different ways to style React components?

Main styling approaches:

  • CSS classes: Traditional CSS with className prop
  • Inline styles: Style objects passed to style prop
  • CSS Modules: Scoped CSS that prevents conflicts
  • CSS-in-JS: Libraries like styled-components, emotion
  • Utility frameworks: Tailwind CSS, Bootstrap

Best practices: Use className for static styles, inline styles for dynamic values, CSS Modules or CSS-in-JS for component-scoped styles.

Remember: Use className instead of class in JSX, and style prop expects an object, not a string.

State Management and Updates

Back to Top
How does React handle state updates?

React state updates are asynchronous and batched for performance. React groups multiple state updates together and applies them all at once.

Key behaviors:

  • State updates don't happen immediately
  • Multiple setState calls are batched together
  • React re-renders after all updates are applied
  • Always use functional updates for state that depends on previous state

Best practices: Don't rely on state values immediately after setting them, use useEffect to respond to state changes, prefer functional updates when new state depends on old state.

Internationalization (i18n)

Back to Top
How do you implement internationalization in React?

Internationalization (i18n) means making your app work in different languages and regions. It involves translating text, formatting dates/numbers, and handling different text directions.

What you need to handle:

  • Text translation
  • Date and number formatting
  • Currency display
  • Right-to-left (RTL) languages
  • Pluralization rules

Popular libraries: react-i18next (most popular), React Intl, LinguiJS.

Best practices: Extract all text to translation files, use translation keys, test with longer languages, consider cultural differences beyond language.

Dynamic Imports

Back to Top
How do dynamic imports work in React?

Dynamic imports let you load JavaScript modules on-demand instead of loading everything upfront. This makes your initial app bundle smaller and faster to load.

How it works: Instead of importing at the top of the file, you import when you actually need the code (like when user clicks a button or navigates to a page).

Common uses:

  • Loading different pages/routes
  • Loading features only when needed
  • Loading heavy libraries conditionally

React integration: Use React.lazy() with dynamic imports and Suspense to handle loading states gracefully.

Benefits: Smaller initial bundle, faster startup, better user experience, reduced bandwidth usage.

Refs and React.memo

Back to Top
How do useRef and React.memo work?

React provides Refs and memoization utilities to help with performance optimization and DOM manipulation.

🔹 useRef

useRef is a React hook that creates a mutable reference object which persists across renders. Changing its .current value does not trigger re-renders.

Common use cases:

  • Accessing and manipulating DOM elements directly.
  • Storing values between renders without causing re-renders.
  • Tracking previous state or prop values.
  • Storing timers, intervals, or mutable objects.

// Example: Accessing DOM element
import React, { useRef, useEffect } from "react";

function InputFocus() {
    const inputRef = useRef(null);

    useEffect(() => {
        inputRef.current.focus(); // Focus input on mount
    }, []);

    return <input ref={inputRef} placeholder="Type here..." />;
}
                        
🔹 React.memo

React.memo is a higher-order component (HOC) that memoizes a functional component. It prevents unnecessary re-renders when the component’s props have not changed.

When to use React.memo:

  • For components that render frequently with the same props.
  • For expensive UI components that take time to render.
  • For leaf components in large component trees.

// Example: Memoized Component
import React from "react";

const Child = React.memo(({ value }) => {
    console.log("Child rendered");
    return <p>Value: {value}</p>;
});

function Parent() {
    const [count, setCount] = React.useState(0);

    return (
        <div>
            <button onClick={() => setCount(count + 1)}>Increment</button>
            <Child value="Hello" /> {/* Won't re-render unless "value" changes */}
        </div>
    );
}
                        
🔑 Summary:
  • useRef: Persistent, mutable value that does not trigger re-renders. Best for DOM access and non-UI state.
  • React.memo: Prevents unnecessary re-renders of functional components when props stay the same.

Best Practice: Use useRef for DOM/timers/stateful refs and React.memo for performance optimization. Don’t overuse memoization; apply it only when needed.

Redux Flow in React

Back to Top
Explain the Redux flow in React.

Redux flow in React involves actions, reducers, store, and components to manage state in a centralized manner.

  • Actions: Dispatched to describe what happened in the application.
  • Reducers: Specify how the state changes in response to actions.
  • Store: Holds the state of the application.
  • Components: Connect to the store to access and update the state.

JSX in React

Back to Top
What is JSX in React?

JSX is a syntax extension for JavaScript used in React to write HTML-like code within JavaScript.

  • Allows developers to write HTML-like code directly in JavaScript files.
  • Makes the code more readable and easier to understand.
  • Gets transpiled into regular JavaScript by tools like Babel before being rendered by the browser.

useMemo Hook

Back to Top
What is useMemo and what are its use cases?

useMemo: A hook that memoizes the result of a function and returns the cached value on subsequent renders.

  • Optimizes performance by avoiding unnecessary recalculations.
  • Takes two arguments: a function and a dependency array.
  • The function re-executes only if dependencies change.
  • Common use cases: expensive calculations, filtering, sorting.

Example: useMemo(() => calculateExpensiveValue(a, b), [a, b])

Single Page Application (SPA)

Back to Top
What is a single-page application?

A single-page application (SPA) is a web app that loads once and dynamically updates content without refreshing the page.

  • Loads once and updates dynamically.
  • No page refreshes required.
  • Uses frameworks like React for routing and rendering.
  • Improves user experience with a seamless and responsive interface.

Advantages of React

Back to Top
What are the advantages of React?

React provides efficient and flexible UI rendering, component reusability, and easy integration with other libraries.

  • Virtual DOM enables faster rendering and improved performance.
  • Component-based architecture promotes reusability and modularity.
  • Easily integrates with libraries/frameworks like Redux and React Native.
  • JSX syntax simplifies building complex UI components.
  • Strong community with extensive resources and support.

Optimization in React

Back to Top
What are some optimization techniques in React?
  • Use React.memo: Prevents re-renders of functional components if props haven’t changed.
  • useCallback & useMemo: Memoize functions and computed values to avoid unnecessary recalculations.
  • Code Splitting: Load code on demand using dynamic imports and React.lazy.
  • Virtualization: Render only visible list items with libraries like react-window or react-virtualized.
  • Lazy Loading Images/Components: Improves initial load time.
  • Batching State Updates: Reduces unnecessary re-renders by grouping updates.

useSelector Hook

Back to Top
Explain useSelector in React-Redux.

useSelector: A React-Redux hook used to extract data from the Redux store state.

  • It takes a selector function as an argument.
  • Automatically subscribes to the Redux store.
  • Re-renders the component only when the selected state changes.
  • Helps avoid unnecessary re-renders by selecting only required pieces of state.

Example: const user = useSelector((state) => state.user)

TypeScript vs JavaScript

Back to Top
What is the difference between TypeScript and JavaScript?
  • TypeScript: A superset of JavaScript that adds static typing, interfaces, and advanced tooling support.
  • JavaScript: A dynamically typed scripting language primarily used for web development.
  • TypeScript code compiles to JavaScript before running in the browser.
  • TypeScript helps catch errors during development with type checking.
  • JavaScript is more flexible but prone to runtime errors due to lack of type safety.

CSS Box Model & Selectors

Back to Top
Explain the CSS Box Model and CSS Selectors.

CSS Box Model: Every HTML element is considered a box with the following parts:

  • Content: The actual text, image, or content.
  • Padding: Space between content and border.
  • Border: Surrounds the padding and content.
  • Margin: Space outside the border (separates element from others).

CSS Selectors: Patterns used to select elements for styling.

  • Element Selector: div { }
  • Class Selector: .classname { }
  • ID Selector: #id { }
  • Attribute Selector: [type="text"] { }
  • Pseudo-classes: a:hover { }
  • Pseudo-elements: p::first-letter { }

Debouncing & Throttling

Back to Top
Explain Debouncing and Throttling in JavaScript.

Debouncing: Ensures that a function is executed only after a specified delay has passed since the last time it was invoked. Useful for actions like search input, resize, or keypress events.

  • Example: Wait until the user stops typing for 300ms before triggering an API call.
  • Code:
  • 
    function debounce(fn, delay) {
        let timer;
        return function(...args) {
            clearTimeout(timer);
            timer = setTimeout(() => fn.apply(this, args), delay);
        };
    }
                                

Throttling: Ensures that a function is executed at most once in a specified interval, no matter how many times the event is triggered. Useful for scroll, resize, or mouse move events.

  • Example: Trigger an API call every 500ms while scrolling, regardless of how many scroll events fire.
  • Code:
  • 
    function throttle(fn, limit) {
        let lastCall = 0;
        return function(...args) {
            const now = Date.now();
            if (now - lastCall >= limit) {
                lastCall = now;
                fn.apply(this, args);
            }
        };
    }
                                

PropTypes

Back to Top
What are PropTypes in React?

Definition: PropTypes is a built-in type checking feature in React that lets you specify the types of props a component should receive. It helps catch bugs by ensuring that components get the correct prop types.

Why it's useful:

  • Validates props passed to components during development.
  • Helps prevent runtime errors caused by incorrect prop types.
  • Serves as documentation for the expected props.

Common PropTypes:

  • PropTypes.string
  • PropTypes.number
  • PropTypes.bool
  • PropTypes.array
  • PropTypes.object
  • PropTypes.func
  • PropTypes.node (anything that can be rendered: numbers, strings, elements, arrays, or fragments)
  • PropTypes.element (a React element)
  • PropTypes.any (any type)

Example:


import PropTypes from 'prop-types';

function Button({ label, onClick, disabled }) {
    return (
        <button onClick={onClick} disabled={disabled}>
            {label}
        </button>
    );
}

// Define prop types
Button.propTypes = {
    label: PropTypes.string.isRequired,
    onClick: PropTypes.func,
    disabled: PropTypes.bool
};

// Default props
Button.defaultProps = {
    onClick: () => {},
    disabled: false
};
                        

Testing in React

Back to Top
How do you test React applications?

Definition: Testing in React means verifying that components, logic, and UI behave as expected. It helps catch bugs early and makes apps more reliable.

Types of testing in React:

  • Unit Testing: Testing small pieces like functions or components.
  • Integration Testing: Testing how multiple components work together.
  • End-to-End (E2E) Testing: Testing the entire app flow like a real user (e.g., login, checkout).

Popular tools:

  • Jest → JavaScript testing framework (comes with Create React App).
  • React Testing Library (RTL) → For testing components in a way closer to how users interact with them.
  • Cypress / Playwright → For end-to-end browser testing.

Example with React Testing Library:


import { render, screen, fireEvent } from '@testing-library/react';
import Button from './Button';

test('button click updates text', () => {
    render(<Button />);
    const btn = screen.getByRole('button');

    fireEvent.click(btn);

    expect(btn).toHaveTextContent('Clicked');
});
                        

Best Practice: Test behavior (what the user sees and does), not implementation details.

Styled Components

Back to Top
What are Styled Components in React?

Definition: Styled Components is a popular library for React that lets you write CSS directly in JavaScript files using a technique called CSS-in-JS. It allows you to create styled React components with scoped styles.

Why use it?

  • Styles are scoped to components (no conflicts with global CSS).
  • Dynamic styling using props.
  • Cleaner and reusable component-based styling.

Example:


import styled from 'styled-components';

// Create a styled button
const Button = styled.button`
    background: ${props => props.primary ? "blue" : "gray"};
    color: white;
    padding: 10px 20px;
    border: none;
    border-radius: 5px;
    cursor: pointer;
`;

function App() {
    return (
        <div>
            <Button>Normal Button</Button>
            <Button primary>Primary Button</Button>
        </div>
    );
}
                        

Best Practice: Use styled-components for component-level styles and avoid mixing too much global CSS.

↑ Top