notes


React.js

Interview Preparation Notes

to do -- add add about suspense in react.js https://www.youtube.com/watch?v=wIyHSOugGGw&list=PPSV and https://www.youtube.com/watch?v=6MYc-ZewjVU&list=PLkMY2Sn6ZX3m_YIbwL8vNos98pkpeIzaD&index=42 redux thunk , redux saga , react routing , lazy loading , memorization .

1️⃣ Virtual DOM
  • React creates a lightweight copy of the real DOM called the Virtual DOM.
  • Whenever state or props change, React updates the Virtual DOM first.
  • It compares the updated Virtual DOM with the previous version.
2️⃣ Diffing Algorithm (Reconciliation)
  • React uses a smart diffing algorithm to compare old and new Virtual DOM trees.
  • Instead of re-rendering the entire DOM, React finds only the changed nodes.
  • This process is called Reconciliation.
  • React uses keys to efficiently track list changes.
3️⃣ Rendering Process
  • State/Props change → Virtual DOM updates
  • Diffing happens
  • Only changed elements are updated in the real DOM
  • This makes React fast and efficient.
4️⃣ Fiber Architecture
  • React Fiber is the internal engine of React.
  • It allows incremental rendering.
  • Supports features like Concurrent Mode.
  • Improves UI responsiveness.
5️⃣ Why Babel is Used
  • Browsers do not understand JSX directly.
  • Babel converts JSX into regular JavaScript that browsers can execute.
  • Babel also transpiles modern ES6+ syntax to widely supported JavaScript.
  • Often used together with Webpack via babel-loader.
  • Example (JSX to JS):
JSX:
<h1>Hello</h1>

Converted by Babel:
React.createElement("h1", null, "Hello");
6️⃣ Webpack in React (Bundling)
  • Webpack is a module bundler that builds a dependency graph starting from entry points.
  • It bundles JS, CSS, images, etc., into optimized assets for the browser.
  • Uses loaders to transform files (e.g., babel-loader for JSX/TS, css-loader/style-loader for CSS).
  • Plugins extend capabilities (e.g., HtmlWebpackPlugin, DefinePlugin, MiniCssExtractPlugin).
  • DevServer enables HMR (Hot Module Replacement) for fast local development.
// webpack.config.js (basic example)
const path = require('path');

module.exports = {
  mode: 'development',
  entry: './src/index.jsx',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
    publicPath: '/',
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/i,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: { presets: ['@babel/preset-env', '@babel/preset-react'] }
        }
      },
      { test: /\.css$/i, use: ['style-loader', 'css-loader'] }
    ]
  },
  resolve: { extensions: ['.js', '.jsx'] },
  devServer: { historyApiFallback: true, hot: true }
};

  • Class components use lifecycle methods.
  • Functional components use Hooks.
  • Modern React prefers functional components.

  • Used to manage local component state.
  • Triggers re-render when state updates.

import { useState } from "react";

function Counter() {
  const [count, setCount] = useState(0);

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

  • Used for complex state logic.
  • Better for managing multiple related state values.
  • Similar to Redux reducer pattern.

  import { useReducer } from "react";

function reducer(state, action) {
  switch(action.type) {
    case "increment":
      return { count: state.count + 1 };
    default:
      return state;
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, { count: 0 });

  return (
    <button onClick={() => dispatch({ type: "increment" })}>
      Count: {state.count}
    </button>
  );
}

  • Used to consume values from Context API.
  • Avoids prop drilling.

import { useContext } from "react";
import { ThemeContext } from "./ThemeContext";

function Button() {
  const theme = useContext(ThemeContext);
  return <button style=>Click</button>;
}

  • Access DOM elements directly.
  • Stores mutable values without re-rendering.

import { useRef } from "react";

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

  const focusInput = () => {
    inputRef.current.focus();
  };

  return (
    <>
      <input ref={inputRef} />
      <button onClick={focusInput}>Focus</button>
    </>
  );
}

  • Used for side effects (API calls, subscriptions, timers).
  • Runs after render.
  • Dependency array controls execution.

import { useEffect, useState } from "react";

function Timer() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setCount(prev => prev + 1);
    }, 1000);

    return () => clearInterval(interval);
  }, []);

  return <h1>{count}</h1>;
}

  • Memoizes expensive computed values.
  • Prevents unnecessary recalculations.

import { useMemo } from "react";

function Expensive({ num }) {
  const squared = useMemo(() => {
    console.log("Calculating...");
    return num * num;
  }, [num]);

  return <p>Result: {squared}</p>;
}

  • Memoizes function references.
  • Prevents unnecessary re-renders of child components.

import { useCallback } from "react";

function Parent() {
  const handleClick = useCallback(() => {
    console.log("Clicked");
  }, []);

  return <Child onClick={handleClick} />;
}

  • useState → Simple state
  • useReducer → Complex state logic
  • useContext → Global data
  • useRef → DOM access / mutable values
  • useEffect → Side effects
  • useMemo → Memoize values
  • useCallback → Memoize functions

Context API allows sharing global data without prop drilling.

  • Create using React.createContext()
  • Wrap with Provider
  • Consume using useContext()

Pure Component
  • Same output for same props & state.
  • No side effects inside render.
  • Predictable and easy to test.

function Greeting({ name }) {
  return <h1>Hello {name}</h1>;
}

Impure Component
  • Output may change without prop/state change.
  • Uses external variables or random values.

let count = 0;

function Counter() {
  count++;
  return <h1>Count: {count}</h1>;
}

React.PureComponent vs React.memo
Feature React.PureComponent React.memo()
Used With Class Components Functional Components
Optimization Type Shallow comparison of props & state Shallow comparison of props only
Syntax class MyComp extends React.PureComponent export default React.memo(MyComp)
Custom Comparison No built-in custom comparison Can pass custom comparison function
Modern Usage Less preferred now Preferred in modern React

Interview Tip: Prefer React.memo in modern React applications since functional components are the standard now.

What are Portals?

Portals allow rendering a component outside its parent DOM hierarchy while keeping it inside the same React component tree.

  • Used for Modals, Tooltips, Dropdowns, Overlays.
  • Helps avoid CSS overflow / z-index issues.
  • Still supports event bubbling through React tree.

How Portals Work

Instead of rendering inside #root, you render into another DOM node.

Step 1: Add a div in index.html

<div id="root"></div>
<div id="portal-root"></div>
Step 2: Create Portal Component

import ReactDOM from "react-dom";

function Modal({ children }) {
  return ReactDOM.createPortal(
    <div className="modal">
      {children}
    </div>,
    document.getElementById("portal-root")
  );
}
Step 3: Use It

function App() {
  return (
    <>
      <h1>Main App</h1>
      <Modal>
        <p>This is rendered using Portal</p>
      </Modal>
    </>
  );
}

Key Interview Points
  • Portals do NOT break React’s event bubbling.
  • They only change DOM placement, not React hierarchy.
  • Useful for UI layers (modals, popups).

Interview Tip: Portals solve UI layering problems without breaking React’s component structure.

Redux Thunk
  • Thunk is a middleware that lets you write action creators returning a function instead of an action.
  • Great for simple async flows: dispatch before/after API calls.
  • Lower learning curve and smaller bundle size.
// actions.js
export const fetchUsers = () => async (dispatch, getState) => {
  dispatch({ type: 'USERS_REQUEST' });
  try {
    const res = await fetch('/api/users');
    const data = await res.json();
    dispatch({ type: 'USERS_SUCCESS', payload: data });
  } catch (err) {
    dispatch({ type: 'USERS_FAILURE', error: err.message });
  }
};

// store.js
import { applyMiddleware, createStore } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducer';

const store = createStore(rootReducer, applyMiddleware(thunk));

Redux Saga
  • Saga is a middleware for managing complex async side effects using generator functions.
  • Provides powerful effects like takeEvery, takeLatest, call, put, and cancellation.
  • Great for orchestrating flows, retries, debouncing, and complex business logic.
// sagas.js
import { call, put, takeLatest } from 'redux-saga/effects';

function* fetchUsersWorker() {
  try {
    const res = yield call(fetch, '/api/users');
    const data = yield call([res, 'json']);
    yield put({ type: 'USERS_SUCCESS', payload: data });
  } catch (err) {
    yield put({ type: 'USERS_FAILURE', error: err.message });
  }
}

export function* usersSaga() {
  yield takeLatest('USERS_REQUEST', fetchUsersWorker);
}

// store.js
import createSagaMiddleware from 'redux-saga';
import { applyMiddleware, createStore } from 'redux';
import rootReducer from './reducer';
import { usersSaga } from './sagas';

const sagaMiddleware = createSagaMiddleware();
const store = createStore(rootReducer, applyMiddleware(sagaMiddleware));
sagaMiddleware.run(usersSaga);

Thunk is a Redux middleware that allows action creators to return a function instead of an action object. Redux Thunk is middleware that allows action creators to return functions instead of objects, enabling asynchronous logic like API calls before dispatching actions.

When to Choose Which?
  • Thunk: Simple async needs, few API calls, minimal orchestration.
  • Saga: Complex workflows, background tasks, cancellation, debouncing, sequencing.

Interview Tip: Start with Thunk for simplicity; move to Saga when side-effect complexity grows and testability/orchestration become priorities.