React Interview Questions


What is React?

React(aka React.js or ReactJS) is an open-source front-end JavaScript library that is used for building composable user interfaces, especially for single-page applications. It is used for handling the view layer for web and mobile apps based on components in a declarative approach. React was created by Jordan Walke, a software engineer working for Facebook. React was first deployed on Facebook's News Feed in 2011 and on Instagram in 2012.

What is the history behind React evolution?

The history of ReactJS started in 2010 with the creation of XHP. XHP is a PHP extension that improved the syntax of the language such that XML document fragments become valid PHP expressions, and the primary purpose was to create custom and reusable HTML elements. The main principle of this extension was to make front-end code easier to understand and to help avoid cross-site scripting attacks. The project was successful in preventing the malicious content submitted by the scrubbing user. However, there was a different problem with XHP in which dynamic web applications require many roundtrips to the server, and XHP did not solve this problem. Also, the whole UI was re-rendered for a small change in the application. Later, the initial prototype of React was created with the name FaxJ by Jordan, inspired by XHP. finally, after some time, React has been introduced as a new library into the JavaScript world.

Note: JSX comes from the idea of XHP

What are the major features of React?

The major features of React are:

  • Uses JSX syntax, a syntax extension of JS that allows developers to write HTML in their JS code.
  • It uses Virtual DOM instead of Real DOM considering that Real DOM manipulations are expensive.
  • Supports server-side rendering, which is useful for Search Engine Optimizations(SEO).
  • Follows Unidirectional or one-way data flow or data binding.
  • Uses reusable/composable UI components to develop the view.

What is JSX?

JSX stands for JavaScript XML and it is an XML-like syntax extension to ECMAScript. Basically it just provides the syntactic sugar for the React.createElement(type, props, ...children) function, giving us expressiveness of JavaScript along with HTML like template syntax. In the example below, the text inside <h1> tag is returned as JavaScript function to the render function.

export default function App() {
  return (
      <h1 className="greeting">{"Hello, this is a JSX Code!"}</h1>
  );
}

If you don't use JSX syntax then the respective JavaScript code should be written as below,

import { createElement } from 'react';

export default function App() {
  return createElement(
    'h1',
    { className: 'greeting' },
    'Hello, this is a JSX Code!'
  );
}

Class is given below.

class App extends React.Component {
  render() {
    return (
        <h1 className="greeting">{"Hello, this is a JSX Code!"}</h1>
    );
  }
}

Note: JSX is stricter than HTML

What is the difference between Element and Component?

An Element is a plain object describing what you want to appear on the screen in terms of the DOM nodes or other components. Elements can contain other Elements in their props. Creating a React element is cheap. Once an element is created, it cannot be mutated.

The JavaScript representation(Without JSX) of React Element would be as follows:

const element = React.createElement("div", { id: "login-btn" }, "Login");

and this element can be simiplified using JSX

<div id="login-btn">Login</div>

The above React.createElement() function returns an object as below:

{
  type: 'div',
  props: {
    children: 'Login',
    id: 'login-btn'
  }
}

Finally, this element renders to the DOM using ReactDOM.render(). Whereas a component can be declared in several different ways. It can be a class with a render() method or it can be defined as a function. In either case, it takes props as an input, and returns a JSX tree as the output:

const Button = ({ handleLogin }) => (
  <div id={"login-btn"} onClick={handleLogin}>
    Login
  </div>
);

Then JSX gets transpiled to a React.createElement() function tree:

const Button = ({ handleLogin }) =>
  React.createElement(
    "div",
    { id: "login-btn", onClick: handleLogin },
    "Login"
  );

How do browsers read JSX?

In general, browsers are not capable of reading JSX and only can read pure JavaScript. The web browsers read JSX with the help of a transpiler. Transpilers are used to convert JSX into JavaScript. The transpiler used is called Babel

What are the main features of React?

The main features of React include JSX (JavaScript XML), Components, Virtual DOM, One-way Data Binding, and Performance Optimization.

What is the Virtual DOM?

The Virtual DOM is a lightweight copy of the actual DOM. React uses it to optimize DOM manipulation by updating the virtual DOM first and then applying the minimal necessary changes to the real DOM.

What are Components in React?

Components are the building blocks of a React application. They are reusable pieces of UI that can have their own state and props.

What is the difference between state and props in React?

State is a local data storage that is mutable and controlled by the component itself, while props are read-only and passed from a parent component to a child component.

What is the purpose of a key in React?

The purpose of a key in React is to help it keep track of lists of items. Imagine you have a list of items, like a to-do list. Each item in the list needs a way to be identified uniquely so React knows which ones are added, removed, or changed. Think of keys as special labels attached to each item in the list. These labels help React efficiently update the list when something changes. They're like nametags for each item, ensuring React knows exactly which one is which, even if the list gets shuffled around.

import React, { useState } from 'react';

const TodoList = () => {
  const [todos, setTodos] = useState([
    { id: 1, text: 'Learn React' },
    { id: 2, text: 'Build a project' },
    { id: 3, text: 'Deploy to production' }
  ]);

  const addTodo = () => {
    const newTodo = { id: todos.length + 1, text: 'New task' };
    setTodos([...todos, newTodo]);
  };

  const removeTodo = (id) => {
    setTodos(todos.filter(todo => todo.id !== id));
  };

  return (
    <div>
      <h2>My Todo List</h2>
      <button onClick={addTodo}>Add Todo</button>
      <ul>
        {todos.map(todo => (
          <li key={todo.id}>
            {todo.text}
            <button onClick={() => removeTodo(todo.id)}>Remove</button>
          </li>
        ))}
      </ul>
    </div>
  );
};

export default TodoList;

How does React handle events?

React wraps native events in its own SyntheticEvent system for cross-browser compatibility. Events are passed as functions to elements as props.

What is a Higher-Order Component (HOC)?

A Higher-Order Component is a function that takes a component and returns a new component, often used for reusing component logic.

import React from 'react';

const withLogger = (WrappedComponent) => {
  return class extends React.Component {
    componentDidMount() {
      console.log('Component mounted');
    }

    render() {
      return <WrappedComponent {...this.props} />;
    }
  };
};

const Hello = () => <h1>Hello, world!</h1>;

const EnhancedHello = withLogger(Hello);

export default EnhancedHello;

What are hooks in React?

Hooks are functions that let you use state and other React features in functional components. Common hooks include useState, useEffect, and useContext.

What is useState?

useState is a React hook that allows you to add state to functional components. It returns an array with the current state and a function to update it.

import React, { useState } from 'react';

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

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

export default Counter;

What is useEffect?

useEffect is a React hook that lets you perform side effects in function components, similar to lifecycle methods in class components. It runs after the render.

import React, { useEffect } from 'react';

const Logger = () => {
  useEffect(() => {
    console.log('Component mounted');
  }, []); // Empty dependency array ensures it runs only once

  return <div>Check the console</div>;
};

export default Logger;

What is the useContext hook?

useContext is a React hook that allows you to access the value of a context directly without using a Consumer component.

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

const MyContext = createContext();

const Display = () => {
  const value = useContext(MyContext);
  return <p>{value}</p>;
};

const App = () => {
  return (
    <MyContext.Provider value="Hello from context!">
      <Display />
    </MyContext.Provider>
  );
};

export default App;

How do you handle forms in React?

Forms in React are handled using controlled components where form data is managed by the component's state.

import React, { useState } from 'react';

const NameForm = () => {
  const [name, setName] = useState('');

  const handleChange = (event) => {
    setName(event.target.value);
  };

  const handleSubmit = (event) => {
    alert('A name was submitted: ' + name);
    event.preventDefault();
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        Name:
        <input type="text" value={name} onChange={handleChange} />
      </label>
      <button type="submit">Submit</button>
    </form>
  );
};

export default NameForm;

What is the Context API?

The Context API in React is a mechanism for efficiently passing data through the component tree without having to pass props down manually at every level. It provides a way to share values (such as state or theme) between components without explicitly passing props through each level of the tree.

The Context API consists of two main parts:

  • Context Provider: This is a component that provides the context value to its child components. It accepts a value prop and passes that value to all its descendants.
  • Context Consumer: This is a component that consumes the context value provided by the nearest ancestor Provider component. It allows components to access the context value and subscribe to changes.

What is prop drilling and how can you avoid it?

Prop drilling is the process of passing props down multiple levels of a component tree. You can avoid it using Context API or state management libraries like Redux.

  • Context API: It allows you to share data between components without passing props manually through every level of the component tree. You can create a context at a higher level and provide it to the components that need access to the data.
  • State Management Libraries (Redux): These libraries provide a centralized store for application state. Instead of passing props through multiple levels, you can connect the components directly to the store to access the state they need.

What is Redux?

Redux is a JavaScript library for managing application state. It stores all the state of an application in a single object called the store. Actions are dispatched to update the state, and reducers specify how the state should change in response to actions. Redux encourages immutability and provides powerful debugging tools like time travel debugging. It's commonly used with React but is compatible with other frameworks as well.

What are pure components?

Pure components are components that only re-render when their props or state change, ensuring better performance by avoiding unnecessary renders.

What is the difference between class components and functional components?

Some key differences between class components and functional components:

Feature Class Components Functional Components
Syntax Defined using ES6 classes Defined as JavaScript functions
Lifecycle Methods Support lifecycle methods (e.g., componentDidMount) Cannot use lifecycle methods
State Can have state using this.state Use useState hook to manage state
Access to Props Access props using this.props Access props as function arguments
Readability More verbose syntax Concise and easier to read syntax
Performance Slightly slower due to overhead Slightly faster due to less overhead

What are React lifecycle methods?

React lifecycle methods are special methods that are automatically invoked at various points in the lifecycle of a React component. These methods allow developers to perform tasks like initializing state, fetching data, and updating the UI in response to changes. Here are the main lifecycle methods in React:

  • constructor(): This method is called when a component is initialized. It's used to initialize state and bind event handlers.
  • componentDidMount(): This method is called after the component has been mounted to the DOM. It's often used to perform tasks like data fetching or setting up subscriptions.
  • componentDidUpdate(): This method is called after the component's updates have been flushed to the DOM. It's useful for performing side effects like updating the DOM in response to prop or state changes.
  • componentWillUnmount(): This method is called just before a component is unmounted and destroyed. It's used to clean up resources like event listeners or subscriptions.
  • static getDerivedStateFromProps(): This method is called before rendering when new props are received. It's used to compute derived state based on the props, which is then passed to the render method.
  • shouldComponentUpdate(): This method is called before rendering when new props or state are received. It's used to determine if the component should re-render or not based on the changes in props or state.
  • getSnapshotBeforeUpdate(): This method is called right before the changes from the virtual DOM are reflected in the actual DOM. It's used to capture information about the DOM before it changes, such as scroll position.

How do you optimize performance in a React application?

To optimize performance in a React application:

  • Functional Components: Prefer functional components over class components whenever possible, as they are lightweight and have better performance.
  • Memoization: Use useMemo hook or React.memo for memoization to avoid unnecessary re-renders of components or calculations.
  • Component Optimization: Use PureComponent for class components or React.memo for functional components to prevent re-renders when props or state haven't changed.
  • Code Splitting: Break your code into smaller, manageable chunks and load them dynamically using React.lazy and Suspense to reduce initial load time.
  • Bundle Size Reduction: Minimize bundle size by utilizing code splitting, tree shaking, and lazy loading. Smaller bundles load faster, improving overall performance.
  • Image Optimization: Compress and optimize images to reduce file size. Employ lazy loading techniques for images not immediately visible on the screen.
  • Virtualization: Implement virtualization for large lists using techniques like windowing or infinite scrolling to render only the visible portion, improving rendering performance.
  • Avoid Inline Functions: Refactor code to prevent creating new function instances inside render methods, as this can lead to unnecessary re-renders. Utilize useCallback to memoize functions when needed.
  • Network Optimization: Minimize network requests and optimize data transfer size by employing techniques like caching, prefetching, and data compression.

What is React Router?

React Router is a library for managing navigation in React applications. It helps you create different pages or views in your app and define which components should render for each URL. With React Router, you can easily set up routes, handle dynamic URLs, and navigate between pages programmatically. It's flexible, easy to use, and integrates seamlessly with React, making it the go-to solution for handling navigation and routing in React applications.

How do you handle errors in React?

In React, we can handle errors using error boundaries, special components that catch errors in their child component tree. By defining a class component with componentDidCatch, you can log errors and display fallback UI when errors occur, preventing crashes and gracefully handling errors in your application.

What is a ref in React?

React is a way to get direct access to a DOM element or a class component instance, allowing you to interact with it imperatively. It's commonly used for managing focus, triggering animations, integrating with third-party libraries, or accessing component methods and properties.

import React, { useRef } from 'react';

const TextInput = () => {
  // Create a ref
  const inputRef = useRef(null);

  // Function to focus the input element when a button is clicked
  const focusInput = () => {
    inputRef.current.focus();
  };

  return (
    <div>
      <input type="text" ref={inputRef} />
      <button onClick={focusInput}>Focus Input</button>
    </div>
  );
};

export default TextInput;

How do you perform AJAX calls in React?

AJAX calls in React are typically performed using the fetch API or libraries like Axios, often within useEffect or componentDidMount.

What is lazy loading in React?

Lazy loading in React means loading parts of your application only when they are needed, rather than loading everything upfront. This improves performance by reducing initial loading times and only fetching and rendering content as it's requested.

How do you implement code splitting in React?

Code splitting can be implemented using dynamic import() statements and React.lazy along with Suspense to load parts of the application only when needed.

What are fragments in React?

Fragments in React are a way to group multiple children elements without adding extra nodes to the DOM. They help improve code organization and avoid unnecessary wrapper elements.

How do you handle state in a large application?

In a large application, managing state effectively becomes crucial for maintaining scalability, performance, and code maintainability.

  • Component Organization: Structure components hierarchically, separating global state management from local state.
  • Context API: Use Context API for global state management, avoiding prop drilling.
  • State Management Libraries: Consider Redux, MobX, or Recoil for complex state management.
  • Local State: Utilize useState hook for simple component-level state.
  • Immutability: Ensure state immutability to prevent side effects and simplify debugging.
  • Asynchronous State: Manage asynchronous state with useEffect hook for data fetching.
  • Component Modularity: Keep components modular and decoupled for easier maintenance.
  • Optimistic UI Updates: Implement optimistic UI updates for responsiveness.
  • Performance Optimization: Memoize calculations, use React.memo, and optimize renders.
  • Testing and Debugging: Write unit tests and use debugging tools for state-related issues.

What are controlled and uncontrolled components?

Controlled and uncontrolled components are two approaches for managing form inputs in React.

  Controlled Components Uncontrolled Components
State Management Controlled by React state Managed by the DOM
Data Synchronization Fully synchronized with React state Not synchronized with React state
React Interaction Uses event handlers to update state Minimal interaction with React
Flexibility More control and flexibility Less control and more reliance on the DOM
Validation Easier to implement validation Validation may require additional handling