DEV Community

Lourdes Suello
Lourdes Suello

Posted on • Edited on

Intermediate React.js interview questions and answers

11. What is React Hooks?
React Hooks allow functional components to use state and lifecycle features without using class components.

Common Hooks:

useState – Manages state.
useEffect – Handles side effects.
useContext – Manages global state.

When talking about useState, useEffect, and useContext, you're diving into the core of React Hooks, which were introduced in React 16.8. Hooks allow you to use state and other React features without writing a class component. Let's break down each one:

useState
Purpose: useState is a Hook that lets you add React state to function components. It's the equivalent of this.state and this.setState in class components.

How it works:

You call useState with the initial state value.
It returns an array with two elements:
The current state value.
A function that lets you update the state.

Example:

import React, { useState } from 'react';

function Counter() {
  // Declare a new state variable called "count" and its updater "setCount"
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Key points:

When the state is updated, the component re-renders.
The setCount function can take either a new value directly or a function that receives the previous state and returns the new state (useful for updates based on the previous state).

useEffect
Purpose: useEffect is a Hook that lets you perform side effects in function components. Side effects are anything that interacts with the "outside world" from your component, such as data fetching, subscriptions, manually changing the DOM, or setting up event listeners. It's the equivalent of componentDidMount, componentDidUpdate, and componentWillUnmount combined in class components.

How it works:

You call useEffect and pass it a function. This function will run after every render of the component (by default).
You can control when the effect runs by providing a second argument: a dependency array.

Example (basic):

import React, { useState, useEffect } from 'react';

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

  // This effect runs after every render
  useEffect(() => {
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Example (with dependency array):

import React, { useState, useEffect } from 'react';

function DataFetcher({ userId }) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    // This effect runs only when userId changes
    setLoading(true);
    fetch(`https://api.example.com/users/${userId}`)
      .then(response => response.json())
      .then(data => {
        setData(data);
        setLoading(false);
      });

    // Cleanup function (optional): runs before the effect re-runs or component unmounts
    return () => {
      // For example, cancel a pending request or clear a timer
      console.log('Cleaning up effect for userId:', userId);
    };
  }, [userId]); // Dependency array: effect re-runs if userId changes

  if (loading) return <p>Loading data...</p>;
  return <p>User Data: {JSON.stringify(data)}</p>;
}
Enter fullscreen mode Exit fullscreen mode

Key points:

No dependency array: Effect runs after every render.
Empty dependency array ([]): Effect runs only once after the initial render (like componentDidMount).
Dependency array with values ([prop1, state1]): Effect runs after the initial render and whenever any value in the dependency array changes.
Cleanup function: The function returned by useEffect is a cleanup function. It runs before the component unmounts or before the effect runs again (if there are dependencies that changed). This is crucial for preventing memory leaks (e.g., clearing timers, unsubscribing from events).

useContext
Purpose: useContext is a Hook that lets you subscribe to React context without introducing nesting. Context provides a way to pass data through the component tree without having to pass props down manually at every level. It's particularly useful for global data like themes, user authentication status, or locale settings.

How it works:

First, you need to create a Context using React.createContext().
Then, you provide a value to components deeper in the tree using Context.Provider.
Finally, within a function component, you use useContext(MyContext) to read the current context value.

Example:

import React, { createContext, useContext, useState } from 'react';

// 1. Create a Context
const ThemeContext = createContext(null);

// Component that provides the theme
function ThemeProvider({ children }) {
  const [theme, setTheme] = useState('light'); // 'light' or 'dark'

  const toggleTheme = () => {
    setTheme(prevTheme => (prevTheme === 'light' ? 'dark' : 'light'));
  };

  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}

// Component that consumes the theme
function ThemeButton() {
  // 2. Consume the Context
  const { theme, toggleTheme } = useContext(ThemeContext);

  return (
    <button onClick={toggleTheme} style={{
      backgroundColor: theme === 'light' ? '#eee' : '#333',
      color: theme === 'light' ? '#333' : '#eee',
      padding: '10px',
      borderRadius: '5px'
    }}>
      Current Theme: {theme} (Click to toggle)
    </button>
  );
}

// Parent component to demonstrate
function App() {
  return (
    <ThemeProvider>
      <div style={{ padding: '20px' }}>
        <h1>My App</h1>
        <ThemeButton />
      </div>
    </ThemeProvider>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Key points:

useContext makes it much cleaner to access context compared to the Context.Consumer render prop pattern.
It simplifies accessing global state or props that are needed deeply in the component tree.
When the context value changes, all components consuming that context will re-render.

In summary, useState, useEffect, and useContext are fundamental Hooks that empower you to build powerful and maintainable React applications using functional components, making your code more readable, reusable, and easier to test.

12. Explain useState, useEffect, and useContext.

import React, { useState, useEffect, useContext, createContext } from "react";

// useState example
function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
}

// useEffect example
function Timer() {
  useEffect(() => {
    console.log("Component mounted!");
    return () => console.log("Component unmounted!");
  }, []);
}

// useContext example
const ThemeContext = createContext("light");
function ThemeComponent() {
  const theme = useContext(ThemeContext);
  return <p>Current theme: {theme}</p>;
}
Enter fullscreen mode Exit fullscreen mode

13. How does useEffect work?
useEffect runs side effects after rendering.

useEffect(() => {
  console.log("Runs after every render");
}, [dependency]); // Runs when 'dependency' changes
Enter fullscreen mode Exit fullscreen mode

14. What is the difference between controlled and uncontrolled components?
Controlled Component – React controls form state.
Uncontrolled Component – Uses the DOM directly.
Example of a controlled component:

function ControlledInput() {
  const [value, setValue] = useState("");
  return <input value={value} onChange={(e) => setValue(e.target.value)} />;
}
Enter fullscreen mode Exit fullscreen mode

15. What is React Router?
React Router is a library for handling navigation in React applications.

Example:

import { BrowserRouter, Route, Routes } from "react-router-dom";
function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
      </Routes>
    </BrowserRouter>
  );
}
Enter fullscreen mode Exit fullscreen mode

16. What is Redux? How does it help in state management?
Redux is a state management library for JavaScript applications, mainly used with React. It helps manage global state by using a single centralized store, making state changes predictable and easier to debug.

How Redux Works?
Store: Holds the global state.
Actions: Describe events (e.g., ADD_TODO).
Reducers: Define how the state changes in response to actions.
Dispatch: Sends actions to reducers.
Example of Redux in React:


import { createStore } from "redux";

// Reducer function
function counterReducer(state = { count: 0 }, action) {
  switch (action.type) {
    case "INCREMENT":
      return { count: state.count + 1 };
    case "DECREMENT":
      return { count: state.count - 1 };
    default:
      return state;
  }
}

// Create store
const store = createStore(counterReducer);

// Dispatch actions
store.dispatch({ type: "INCREMENT" });
console.log(store.getState()); // { count: 1 }
Enter fullscreen mode Exit fullscreen mode

Why Use Redux?

  • Centralized state management
  • Predictable state updates
  • Easier debugging with Redux DevTools
  • Works well for large applications

17. What are Higher-Order Components (HOC)?
A Higher-Order Component (HOC) is a function that takes a component as input and returns a new enhanced component. It’s a way to reuse component logic.

Example of an HOC:

import React from "react";

// HOC function
function withLogger(WrappedComponent) {
  return function EnhancedComponent(props) {
    console.log("Component Rendered:", WrappedComponent.name);
    return <WrappedComponent {...props} />;
  };
}

// Simple component
function Hello() {
  return <h1>Hello, World!</h1>;
}

// Enhanced component
const HelloWithLogger = withLogger(Hello);
Enter fullscreen mode Exit fullscreen mode

Use Cases for HOCs

  • Adding authentication checks
  • Logging or analytics
  • Conditional rendering

18. What is Context API, and when would you use it?
The Context API provides a way to share state globally between components without prop drilling.

How Context API Works?

  1. Create a Context
  2. Provide a value at a higher level in the component tree
  3. Consume the context in any child component Example of Context API:
import React, { createContext, useContext } from "react";

// Create Context
const ThemeContext = createContext("light");

// Theme Provider
function ThemeProvider({ children }) {
  return <ThemeContext.Provider value="dark">{children}</ThemeContext.Provider>;
}

// Consumer Component
function DisplayTheme() {
  const theme = useContext(ThemeContext);
  return <p>Current Theme: {theme}</p>;
}

// Using the context
function App() {
  return (
    <ThemeProvider>
      <DisplayTheme />
    </ThemeProvider>
  );
}
Enter fullscreen mode Exit fullscreen mode

When to Use Context API?

  • When passing state deeply through multiple components
  • For theming, authentication, or language settings

19. Explain the difference between useCallback _and _useMemo.
Both useCallback and useMemo optimize performance by caching functions and values.

Hook Purpose When to Use
useCallback Caches a function reference When passing functions as props to child components
useMemo Caches a computed value When computing expensive calculations

Example of useCallback:

import React, { useState, useCallback } from "react";

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

  // useCallback prevents unnecessary re-renders
  const increment = useCallback(() => {
    setCount((prev) => prev + 1);
  }, []);

  return <button onClick={increment}>Count: {count}</button>;
}
Enter fullscreen mode Exit fullscreen mode

Example of useMemo:

import React, { useState, useMemo } from "react";

function ExpensiveCalculation({ number }) {
  const result = useMemo(() => {
    console.log("Expensive calculation running...");
    return number * 2;
  }, [number]);

  return <p>Result: {result}</p>;
}
Enter fullscreen mode Exit fullscreen mode

Key Differences

  • _useCallback _memoizes functions
  • _useMemo _memoizes computed values

20. What are React Portals?
React Portals allow rendering a component outside the parent component’s DOM hierarchy, typically used for modals, pop-ups, or tooltips.

How to Use React Portals?
Create a div in index.html where you want to render the portal.

<div id="modal-root"></div>
Enter fullscreen mode Exit fullscreen mode

Use ReactDOM.createPortal in your component:

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

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

function App() {
  return (
    <div>
      <h1>Main App</h1>
      <Modal>
        <h2>I'm inside a portal!</h2>
      </Modal>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Why Use Portals?

  • Prevents CSS conflicts (modals remain unaffected by parent styles)
  • Improves accessibility
  • Helps with z-index issues

Top comments (0)