Top 25+ React Interview Questions & Answers | Get AI Expert Help

Excel Your React Interview with Top 20 Must-Know Q&A

Q1: What are the key differences between functional and class components in React?

Functional and class components are the two main types of components in React. Here are the key differences:

Syntax:

Functional Components: These are plain JavaScript functions that return JSX.

function FunctionalComponent() {
  return 
Hello from Functional Component
; }

Class Components: These are ES6 classes that extend React.Component and must have a render method that returns JSX.

class ClassComponent extends React.Component {
  render() {
    return 
Hello from Class Component
; } }

State and Lifecycle Methods:

Functional Components: Prior to React 16.8, functional components were stateless. With the introduction of hooks, they can now manage state and use lifecycle methods.

Class Components: These have built-in support for state and lifecycle methods (e.g., componentDidMount, shouldComponentUpdate).

Performance:

Functional components with hooks can be more performant due to less overhead compared to class components.

Q2: What is JSX and why is it used in React?

JSX stands for JavaScript XML. It is a syntax extension for JavaScript that allows you to write HTML directly within JavaScript. JSX makes it easier to write and understand React components by providing a syntax similar to HTML.

Example:

const element = 

Hello, world!

;

JSX is used in React because it:

  • Makes the code easier to understand and write.
  • Allows developers to see the layout and logic in the same place.
  • Transpiles to React.createElement() calls which provide detailed error and warning messages.

Q3: How does the virtual DOM work in React?

The Virtual DOM (VDOM) is a concept where a virtual representation of the UI is kept in memory and synced with the real DOM using a library such as ReactDOM. This process is known as reconciliation.

How it works:

  1. When a component’s state or props change, React creates a new VDOM tree.
  2. React then compares this new VDOM tree with the previous one (using a process called diffing).
  3. React calculates the minimum number of changes required to update the real DOM to match the new VDOM.
  4. These changes are then efficiently updated in the real DOM.

This approach minimizes direct DOM manipulations, resulting in better performance.

Q4: What are React hooks and why were they introduced?

React hooks are functions that let you use state and other React features in functional components. They were introduced in React 16.8 to address the following issues:

  • Stateful Logic: Hooks allow stateful logic to be reused across components without changing the component hierarchy.
  • Complex Components: They simplify the creation of complex components by breaking them into smaller functions.
  • Class Component Issues: Hooks eliminate the need for class components, reducing the issues related to this binding and lifecycle methods.

Examples of Hooks:

  • useState for state management.
  • useEffect for side effects.
  • useContext for context management.

Q5: Explain the concept of props in React.

Props (short for properties) are read-only attributes used to pass data from a parent component to a child component in React. They allow components to be dynamic and reusable by providing a way to pass data and event handlers down the component tree.

Example:

function ChildComponent(props) {
  return 
{props.message}
; } function ParentComponent() { return ; }

In this example, message is a prop passed from ParentComponent to ChildComponent .

Props are immutable, meaning that a component cannot modify its own props. They should be used for data that a component should receive from its parent.

Request question

Please fill in the form below to submit your question.

Q6: What is state in React and how is it different from props?

State is an object managed within a component that holds information that may change over the component's lifecycle. Unlike props, which are passed to a component from its parent, state is local to the component and can be updated with the setState method in class components or the useState hook in functional components.

Differences between State and Props:

State:

  • Managed within the component.
  • Mutable (can be changed).
  • Used to manage dynamic data that affects the component’s rendering.

Example:

class ExampleComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

  increment = () => {
    this.setState({ count: this.state.count + 1 });
  }

  render() {
    return (
      

Count: {this.state.count}

); } }

Props:

  • Passed from parent to child components.
  • Immutable (cannot be changed by the receiving component).
  • Used to pass data and event handlers down the component tree.

Example:

function DisplayMessage(props) {
  return 

{props.message}

; } function ParentComponent() { return ; }

Q7: What is the context API in React and when would you use it?

The Context API in React provides a way to pass data through the component tree without having to pass props down manually at every level. It is useful for sharing data that needs to be accessed by many components at different nesting levels, such as themes, user authentication, or locale settings.

Usage:

Create a Context:

const MyContext = React.createContext();

Provide Context Value:

function App() {
  return (
    
      
    
  );
}

Consume Context Value:

Using Context.Consumer :

function ChildComponent() {
  return (
    
      {value => 

{value}

}
); }

Using useContext Hook (functional components):

function ChildComponent() {
  const value = React.useContext(MyContext);
  return 

{value}

; }

Q8: How do you handle events in React?

Event handling in React is similar to handling events in DOM elements but with some syntactic differences. React events are named using camelCase, and you pass a function as the event handler rather than a string.

Example:

class ClickComponent extends React.Component {
  handleClick = () => {
    alert('Button clicked!');
  }

  render() {
    return (
      
    );
  }
}

In functional components, you can handle events using hooks:

function ClickComponent() {
  const handleClick = () => {
    alert('Button clicked!');
  };

  return (
    
  );
}

Q9: What are higher-order components (HOCs) in React?

A higher-order component (HOC) is a function that takes a component and returns a new component with additional props or functionality. HOCs are used to reuse component logic.

Example:

function withLogging(WrappedComponent) {
  return class extends React.Component {
    componentDidMount() {
      console.log('Component mounted:', WrappedComponent.name);
    }

    render() {
      return ;
    }
  };
}

const EnhancedComponent = withLogging(MyComponent);

In this example, withLogging is an HOC that adds logging functionality to the MyComponent component.

Q10: What are React fragments and why would you use them?

React fragments let you group a list of children without adding extra nodes to the DOM. This is useful when rendering multiple elements from a component without wrapping them in an extra div or other container element.

Example:

function FragmentComponent() {
  return (
    
      

Title

Description

); }

Shorthand syntax for fragments:

function FragmentComponent() {
  return (
    <>
      

Title

Description

); }

Fragments are used to avoid unnecessary HTML elements in the DOM, which can simplify CSS styling and improve performance.

Request question

Please fill in the form below to submit your question.

Q11: What is the purpose of useEffect in React and how does it work?

The useEffect hook allows you to perform side effects in functional components. Side effects include data fetching, subscriptions, and manually changing the DOM. useEffect runs after the render and ensures the component logic is separate from the side effects.

Syntax:

useEffect(() => {
  // Side effect logic
  return () => {
    // Cleanup logic
  };
}, [dependencies]);

Parameters:

  • Effect function: A function containing the side effect logic.
  • Dependencies array (optional): An array of values that the effect depends on. The effect will only re-run if one of these values changes.

Example:

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

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

  useEffect(() => {
    document.title = `You clicked ${count} times`;
  }, [count]); // Only re-run the effect if count changes

  return (
    

You clicked {count} times

); }

Q12: What is the useState hook and how do you use it in React?

The useState hook allows you to add state to functional components. It returns an array containing the current state value and a function to update that state.

Syntax:

const [state, setState] = useState(initialState);

Parameters:

  • initialState: The initial state value.

Example:

import React, { useState } from 'react';

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

  return (
    

You clicked {count} times

); }

In this example, count is the state variable and setCount is the function to update count . The initial state is set to 0.

Q13: Explain the concept of lifting state up in React.

Lifting state up is a pattern in React where you move state from child components to their closest common ancestor. This allows multiple components to share and synchronize their state.

Scenario: Suppose you have two sibling components that need to share the same state. Instead of managing state separately in each component, you lift the state up to their parent component and pass it down as props.

Example:

function ParentComponent() {
  const [sharedState, setSharedState] = useState('');

  return (
    
); } function ChildComponentA({ sharedState, setSharedState }) { return ( setSharedState(e.target.value)} /> ); } function ChildComponentB({ sharedState }) { return (

{sharedState}

); }

In this example, sharedState is lifted up to ParentComponent , allowing both ChildComponentA and ChildComponentB to access and synchronize the state.

Q14: What are controlled and uncontrolled components in React?

Controlled Components: These are components where React controls the form elements by keeping the form data in the component state. The value of the form element is set by the state and updated via events.

Example:

function ControlledInput() {
  const [value, setValue] = useState('');

  return (
     setValue(e.target.value)} />
  );
}

Uncontrolled Components: These are components where the form data is handled by the DOM itself. You can use a ref to access the form values.

Example:

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

  const handleSubmit = () => {
    alert(inputRef.current.value);
  };

  return (
    
); }

Controlled components are preferred because they provide a more predictable and manageable way to handle form inputs.

Q15: How do you optimize performance in a large React application?

To optimize performance in a large React application, you can follow these best practices:

  • Memoization: Use React.memo to memoize functional components to prevent unnecessary re-renders.
  • const MyComponent = React.memo(function MyComponent(props) {
      /* render using props */
    });
  • useCallback and useMemo: Use useCallback to memoize callback functions.
  • const memoizedCallback = useCallback(() => {
      doSomething(a, b);
    }, [a, b]);
  • Use useMemo to memoize expensive calculations.
  • const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
  • Code Splitting: Use dynamic import statements and React.lazy to load components lazily.
  • const OtherComponent = React.lazy(() => import('./OtherComponent'));
  • Virtualization: Use libraries like react-window or react-virtualized to render only visible items in a large list.
  • Avoid Anonymous Functions in JSX: Define functions outside of JSX to prevent re-creation on every render.
  • function handleClick() {
      // handle click
    }
    
    return ;
  • Avoid Unnecessary Re-renders: Use shouldComponentUpdate or React.PureComponent in class components and React.memo in functional components.
  • Use Profiler: Use React's Profiler to identify performance bottlenecks.

By applying these techniques, you can significantly improve the performance of your React application.

Request question

Please fill in the form below to submit your question.

Q16: What are React Portals and when would you use them?

React Portals provide a way to render children into a DOM node that exists outside the hierarchy of the parent component. They are useful for scenarios where you need to break out of the normal DOM hierarchy, such as rendering modals, tooltips, or dropdowns that overlay other content.

Syntax:

ReactDOM.createPortal(child, container);

Example:

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

function Modal({ children }) {
  return ReactDOM.createPortal(
    
{children}
, document.getElementById('modal-root') ); } function App() { return (

App Component

This is a modal content

); }

In this example, the modal content is rendered into the modal-root div, which is outside the normal DOM hierarchy of the App component.

Q17: What are error boundaries in React and how do you implement them?

Error boundaries are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the component tree that crashed. They help prevent the entire application from crashing due to an error in a part of the UI.

Implementation:

Create an Error Boundary Component:

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    // Log error details
    console.error("Error caught by Error Boundary:", error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      return 

Something went wrong.

; } return this.props.children; } }

Wrap Your Components with Error Boundary:

function App() {
  return (
    
      
    
  );
}

Error boundaries catch errors during rendering, in lifecycle methods, and in constructors of the whole tree below them.

Q18: Explain the concept of reconciliation in React.

Reconciliation is the process by which React updates the DOM with the results of render output. When the state or props of a component change, React compares the newly returned element with the previously rendered one and updates the actual DOM only where there are differences.

Steps in Reconciliation:

  • Diffing Algorithm: React compares the new VDOM with the previous VDOM. It uses heuristics to make this process efficient.
  • Elements of different types produce different trees (e.g.,
    to ).
  • Elements of the same type stay in the same tree and their attributes are updated.
  • Component Updates: If a component's state changes, React re-renders that component and all its children.
  • Key Attribute: For lists, the key attribute helps React identify which items have changed, are added, or are removed.

Example:

function App() {
  const [items, setItems] = useState(['A', 'B', 'C']);

  return (
    
    {items.map(item => (
  • {item}
  • ))}
); }

Using keys, React can efficiently update the list when items are added, removed, or reordered.

Q19: What is the purpose of useReducer hook and how does it work?

The useReducer hook is an alternative to useState for managing complex state logic in functional components. It is particularly useful when the state depends on previous state values or when multiple state transitions share logic.

Syntax:

const [state, dispatch] = useReducer(reducer, initialState);

Parameters:

  • reducer: A function that takes the current state and an action, and returns a new state.
  • initialState: The initial state value.

Example:

import React, { useReducer } from 'react';

const initialState = { count: 0 };

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    

Count: {state.count}

); }

In this example, useReducer manages the state transitions based on the dispatched actions.

Q20: Explain the difference between componentDidMount and useEffect in React.

componentDidMount is a lifecycle method used in class components, while useEffect is a hook used in functional components. Both are used to perform side effects, such as data fetching, subscriptions, or manually modifying the DOM, after the component has been rendered to the DOM.

componentDidMount:

  • Usage: Only available in class components.
  • Timing: Invoked once, immediately after the component is mounted (inserted into the tree).

Example:

class MyComponent extends React.Component {
  componentDidMount() {
    console.log('Component did mount');
  }

  render() {
    return 
Hello, World!
; } }

useEffect:

  • Usage: Available in functional components.
  • Timing: By default, runs after every render. Can be configured to run only once or when specific dependencies change.

Example:

import React, { useEffect } from 'react';

function MyComponent() {
  useEffect(() => {
    console.log('Component did mount');
  }, []); // Empty array means it runs once after the initial render

  return 
Hello, World!
; }

Differences:

  • Class vs. Functional: componentDidMount is for class components, while useEffect is for functional components.
  • Flexibility: useEffect can handle multiple effects and can be configured to run based on dependencies.
  • Cleanup: In useEffect , you can return a cleanup function that runs when the component is unmounted or before the effect runs again.

Request question

Please fill in the form below to submit your question.

Request question

Please fill in the form below to submit your question.

Test Your React Skills: 10 Challenging Practical Interview Q&A

Q1: There is a bug in the following code that causes it not to display the count properly when the button is clicked. Identify and fix the bug.
(Basic)

import React, { useState } from 'react';

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

  const incrementCount = () => {
    setCount(count + 1);
  };

  return (
    

Count: {count}

); } export default Counter;

The code itself does not contain any bugs. However, ensure that there are no external issues such as incorrect imports or render issues in the parent component.

Q2: Create a functional component named TodoList that allows users to add and remove items from a to-do list.
(Basic)

import React, { useState } from 'react';

function TodoList() {
  const [todos, setTodos] = useState([]);
  const [input, setInput] = useState('');

  const addTodo = () => {
    setTodos([...todos, input]);
    setInput('');
  };

  const removeTodo = (index) => {
    setTodos(todos.filter((_, i) => i !== index));
  };

  return (
    
setInput(e.target.value)} />
    {todos.map((todo, index) => (
  • {todo}
  • ))}
); } export default TodoList;
Q3: The following code is supposed to toggle the visibility of a message when the button is clicked, but it is not working as expected. Identify and fix the bug.
(Basic)

import React, { useState } from 'react';

function ToggleMessage() {
  const [isVisible, setIsVisible] = useState(true);

  const toggleVisibility = () => {
    setIsVisible(!isVisible);
  };

  return (
    
{isVisible &&

The message is visible

}
); } export default ToggleMessage;

The code itself is correct and should work as expected. Ensure there are no external issues such as incorrect imports or render issues in the parent component.

Q4: The following component fetches data from an API every time it renders. Optimize it to fetch data only once when the component mounts.
(Intermediate)

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

function DataFetchingComponent() {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(data => setData(data));
  });

  return (
    
{data ?
{JSON.stringify(data, null, 2)}
: 'Loading...'}
); } export default DataFetchingComponent;

Add an empty dependency array to the useEffect hook to ensure the data is fetched only once when the component mounts.


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

function DataFetchingComponent() {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(data => setData(data));
  }, []); // Empty array means the effect runs only once

  return (
    
{data ?
{JSON.stringify(data, null, 2)}
: 'Loading...'}
); } export default DataFetchingComponent;
Q5: Optimize the following component to prevent unnecessary re-renders of the ListItem component when the Counter button is clicked.
(Intermediate)

import React, { useState } from 'react';

function ParentComponent() {
  const [count, setCount] = useState(0);
  const items = ['Item 1', 'Item 2', 'Item 3'];

  return (
    
    {items.map((item, index) => ( ))}
); } function ListItem({ item }) { console.log('ListItem rendered:', item); return
  • {item}
  • ; } export default ParentComponent;

    Use React.memo to memoize the ListItem component.

    
    import React, { useState } from 'react';
    
    function ParentComponent() {
      const [count, setCount] = useState(0);
      const items = ['Item 1', 'Item 2', 'Item 3'];
    
      return (
        
      {items.map((item, index) => ( ))}
    ); } const ListItem = ({ item }) => { console.log('ListItem rendered:', item); return
  • {item}
  • ; }; const MemoizedListItem = React.memo(ListItem); export default ParentComponent;
    Q6: The following component updates its state on every keystroke, causing performance issues. Optimize it by debouncing the input.
    (Intermediate)
    
    import React, { useState } from 'react';
    
    function SearchInput() {
      const [query, setQuery] = useState('');
    
      const handleChange = (e) => {
        setQuery(e.target.value);
      };
    
      return (
        

    Search query: {query}

    ); } export default SearchInput;

    Use a debouncing technique to delay the state update.

    
    import React, { useState, useEffect } from 'react';
    
    function SearchInput() {
      const [query, setQuery] = useState('');
      const [displayedQuery, setDisplayedQuery] = useState('');
    
      useEffect(() => {
        const handler = setTimeout(() => {
          setDisplayedQuery(query);
        }, 300);
    
        return () => {
          clearTimeout(handler);
        };
      }, [query]);
    
      const handleChange = (e) => {
        setQuery(e.target.value);
      };
    
      return (
        

    Search query: {displayedQuery}

    ); } export default SearchInput;
    Q7: Create a functional component named LoginForm that includes fields for username and password and a submit button. On form submission, display an alert with the entered username and password.
    (Intermediate)
    
    import React, { useState } from 'react';
    
    function LoginForm() {
      const [username, setUsername] = useState('');
      const [password, setPassword] = useState('');
    
      const handleSubmit = (e) => {
        e.preventDefault();
        alert(`Username: ${username}, Password: ${password}`);
      };
    
      return (
        
    setUsername(e.target.value)} />
    setPassword(e.target.value)} />
    ); } export default LoginForm;
    Q8: Optimize the following component to prevent unnecessary re-renders of the ChildComponent.
    (Advanced)
    
    import React, { useState } from 'react';
    
    function ParentComponent() {
      const [count, setCount] = useState(0);
    
      return (
        
    ); } function ChildComponent() { console.log('Child component rendered'); return
    Child Component
    ; } export default ParentComponent;

    Use React.memo to memoize the ChildComponent and prevent it from re-rendering unless its props change.

    
    import React, { useState } from 'react';
    
    function ParentComponent() {
      const [count, setCount] = useState(0);
    
      return (
        
    ); } const ChildComponent = () => { console.log('Child component rendered'); return
    Child Component
    ; }; const MemoizedChildComponent = React.memo(ChildComponent); export default ParentComponent;
    Q9: What will be the output of the following code when the button is clicked?
    (Advanced)
    
    import React, { useState } from 'react';
    
    function OutputComponent() {
      const [count, setCount] = useState(0);
    
      const handleClick = () => {
        setCount(count + 1);
        setCount(count + 1);
      };
    
      return (
        

    Count: {count}

    ); } export default OutputComponent;

    The output will be:

    Count: 1

    Explanation: setCount does not update the state immediately. It schedules an update, and the state updates are batched. Both setCount calls will be batched, and only the last one will be applied, resulting in count being incremented by 1 instead of 2.

    Q10: What will be the output of the following code when the button is clicked twice?
    (Advanced)
    
    import React, { useState } from 'react';
    
    function OutputComponent() {
      const [count, setCount] = useState(0);
    
      const handleClick = () => {
        setCount(prevCount => prevCount + 1);
        setCount(prevCount => prevCount + 1);
      };
    
      return (
        

    Count: {count}

    ); } export default OutputComponent;

    The output will be:

    Count: 2

    Explanation: Using the functional update form of setCount ensures that the state updates are based on the previous state. This results in count being incremented by 1 twice, leading to an increment of 2 when the button is clicked twice.

    Request question

    Please fill in the form below to submit your question.

    Level Up Your React Skills – Dive into Workik AI Today!

    Join developers who are using Workik’s AI assistance everyday for programming

    Sign Up Now

    Overview of React

    What is React?

    What is the history and latest trends in React development?

    What are some of the popular frameworks and libraries associated with React?

    • Redux: A state management library for JavaScript apps, commonly used with React.
    • React Router: A collection of navigational components for React applications.
    • Material-UI: A set of React components that implement Google's Material Design.
    • Next.js: A React framework for building server-side rendered and static web applications.
    • Gatsby: A React-based open-source framework for creating fast websites and apps.

    What are the use cases of React?

    • Web Development: Building dynamic and interactive web applications.
    • Single-Page Applications (SPAs): Creating applications that load a single HTML page and dynamically update content as the user interacts with the app.
    • Mobile App Development: Using React Native to build cross-platform mobile applications.
    • UI Components: Developing reusable UI components that can be shared across different parts of an application.
    • E-commerce Sites: Enhancing user interfaces and improving the user experience on e-commerce platforms.

    What are some of the tech roles associated with expertise in React?

    • React Developer: Focuses on building user interfaces using React.
    • Front-End Developer: Works on the client-side of web applications, often using React.
    • Full-Stack Developer: Utilizes React for front-end development and other technologies for back-end development.
    • Mobile Developer: Uses React Native to develop mobile applications.
    • UI/UX Developer: Enhances the user experience and interface of applications using React.

    What pay package can be expected with experience in React?


    Source: glassdoor.com indeed.com

    • Junior React Developer (0-2 years experience): $82,000 - $130,000 per year.
    • Mid-Level React Developer (3-5 years experience): $110,000 - $150,000 per year.
    • Senior React Developer (5+ years experience): $121,000 - $178,000 per year.
    • Front-End Developer with React expertise: $80,000 - $187,000 per year.
    • Full-Stack Developer with React expertise: $90,000 - $140,000 per year.