Top React Interview Questions for Experienced and Beginner Developers

Software Engineering Aug 16, 2022

React is the single most commonly used frontend JavaScript framework, and many of the newer frontend tools such as Next.js use React or much of its methodology. As such, a strong understanding of React is critical for an adept Frontend or Full-Stack Developer.

The following will walk you through several React Interview Questions that are critical to a solid understanding of the library.

Background

React is a JavaScript library though often referred to as a framework. It allows for scalable and fast frontends for web applications that can be developed and delivered quicker than with using only vanilla JavaScript.

React employs a few key and distinctive features those being the Virtual DOM, the Component tree, and JSX. These three features comprise the basic principles of how React works and what made it innovative.

Beginner React Interview Questions

Below, we outline the most common React interview questions and answers for junior developers.

What is the React Virtual DOM and why is it important?

The React Virtual DOM allows for quicker re-renders of the frontend UI. The Virtual DOM is created based off the UI data (HTML, CSS, etc.)

React will then find the discrepancies between the Virtual DOM and the Real DOM, and change the Real DOM accordingly.

This process is significantly quicker than the typical full re-render as with React, only the differences in UI are updated and nothing else. This can allow for quick updates to the UI depending on State and the Component life-cycle.

What is JSX? What are the benefits of JSX?

JSX stands for JavaScript XML. It's the primary syntax used to render UI elements within React and is commonly used across many frameworks.

At a basic level, JSX lets JavaScript code blend seamlessly with HTML, creating a very easy-to-use developer experience. This is possible because JSX compiles down into JavaScript, and therefore can be used with for loops and if-statements.

These capabilities mean that JSX allows for very simple conditional rendering, repeated rendering, and the handling of data directly within what otherwise function as HTML tags.

This coupled with the features of props, State, and component lifecycle makes JSX able to create very powerful applications.

class App extends React.Component {
  render() {
    return(
      <div>
        <h2>{'Welcome to Exponent!'}</h2>
      </div>
    )
  }
}

The text inside the h2 tag is returned as a function in JavaScript when rendered.

In the example below text inside <h1> tag is returned as JavaScript function to the render function.

What are React Components?

Perhaps the single most important concept of React is Components. They can be thought of as a pocket of UI that can be repeatedly rendered across a web-application.

Components can be made either via a Class or a Function.

This is an example of a Function Component.

function Welcome({ message }) {
  return <b>{`Hello, ${message}`}</b>

}

This is an example of a Class Component.

class Welcome extends React.Component {
  render() {
    return <b>{`Hey, ${this.props.message}`}</b>
  }
}

Recently, Functional Components have become the preferred version with the usage of React Hooks.

A Functional Component is simply a JavaScript function that instructs how to render an element (written in JSX). Any Component can contain several more components within them, thus breaking apart the typical HTML page down to a series of components.

This results in what is called a Component tree, where the root Component is comprised of several of its own components, which themselves are comprised of more components, each handling their own logic, state, and UI.

Components can significantly improve time of development by reducing redundant coding.

What are props and how are they passed through React Components?

Props, short for properties, are a basic way of passing data to a React Component. The passing of props happens down the Component tree by providing data as if it were a property on an HTML tag.

In the case of function Components, any props that are passed will be treated as arguments to the function. As such, these props should never be modified by their own Component. Any scenario that calls for such should utilize state instead.

Developers should also be careful when passing props down through components. A codebase becomes less sustainable the more props are drilled through the Component tree.

What is React state and how is it implemented?

State refers to data that is associated with a component that may change, thus causing a re-render of that component. It can be used to create highly interactive UI elements that update at the press of a button.

State is often used to handle and render data from APIs, complement complex CSS, and determine how an element is rendered.

State is handled in React most commonly through the React hook useState. It can be used to establish some data associated with any given component that may be updated, also through the useState hook.  

Class components were once the only way to have stateful components. Due to React hooks, however, functional components have become a more succinct, developer-friendly method for implementing state.

Explain the React Component lifecycle

Every component has a lifecycle. The component is mounted, the component is updated, and the component is unmounted. Note that any update to the component's State and the like constitutes as an update to the component.

In any of these instances, a side-effect to a change in the component life-cycle may be created using lifecycle methods. These methods allow for greater control of

It used to be that each of these scenarios would be handled independently using a Class Component. However, much like the concept of state, the built-in React hook useEffect has come to provide a cleaner solution with Function Component.

Explain the basic pre-built React Hooks

React hooks provide some of the most useful tools to build functionality into your UI. There are a total of 10 pre-built hooks, along with the ability to add custom hooks. However, the following four are the basic React hooks that you should absolutely know before going into an interview.

useState()

The useState() hook is by far the most commonly used React hook. It allows for state within a functional component that can be updated. The hook may be used multiple times to track the state of multiple different properties.

The below shows an example of the useState hook. There's an initialized value held in the variable count. This can be updated using setCount().

import React, { useState } from 'react';

function Example() {
  const [count, setCount] = useState(0);
  
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click
      </button>
    </div>
  );
}
Notice how setCount() is being used to declare the new value of count

Note that state is still immutable and can only be modified using setCount() and passing the new version of count. This replaces the concepts of prevState and the need for binding state to a Class. As such, the logic for creating state within a function becomes several times easier to manage.

useEffect()

The useEffect() hook is made for the purpose of creating side-effects during a change to the component's lifecycle i.e. if the component updated, mounted, or unmounted.

Using this hook means providing it with a function that will be executed automatically upon a change to the component lifecycle. This may be to process data, send an API request, or otherwise.

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

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

  useEffect(() => {
 	document.title = `You clicked ${count} times`; 
  });
  
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click
      </button>
    </div>
  );
}
Typically, useEffect is utilized in conjunction with useState. Here, the state is being updated and the side effect is that the document's title is updated.

Note that infinite loops are very easy to create with the useEffect() hook. For instance, if a side effect of an updated state is updating a different state, there will be an infinite loop.

To avoid this, be careful to provide a list as an argument in useEffect() that delimits precisely when the useEffect() activates, whether that be an update to a specific state or only when the component is mounted.

useContext()

The useContext() hook may be used to avoid the malpractice of prop drilling. This is when several components pass along a state from a parent component to a child component even though several of the components in the chain did not utilize the state they were passing.

useContext() avoids this by hooking into React's context API. Retrieving data from the context that was declared in the parent component and directly passing it to the child component.

function Component1() {
  const [user, setUser] = useState("Exponent User");

  return (
    <UserContext.Provider value={user}>
      <h1>{`Hello ${user}!`}</h1>
      <Component2 />
    </UserContext.Provider>
  );
}


function Component5() {
  const user = useContext(UserContext);

  return (
    <>
      <h1>Component 5</h1>
      <h2>{`Hello ${user}!`}</h2>
    </>
  );
}
In this example, Component 5 is several layers beneath Component 1 in the Component Tree, however the Context API allows Component5 to retrieve state that was established much higher.

useReducer()

The useReducer() hook is perhaps the most complicated of the basic hooks. It is essentially an alternative to the useState() hook where complex updating logic is needed.

const initialState = {count: 0}; //sets the initial state

//reducer function
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 (
    <>
    //returning the state
      Count: {state.count}
    //letting the reducer function know if the button was decrement or increment via the dispatch
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}
This is an example from the react documentation of a complex counting state handled using the useReducer hook 

The useReducer() hook will accept a reducer function that handles the complex logic and an initial state while returning the state and a dispatch function. This function is what causes any state change.

Advanced React Interview Questions

Below, we outline the most common React interview questions and answers for senior developers.

Explain the concept of keys in React

Keys need to be used whenever rendering a list of elements in React. They're typically a string attribute that uniquely identifies every element that is being rendered in the list.

How is JSX read by the Browser?

This is a trick-question, the Browser can not understand JSX. It can only understand JavaScript Objects, but JSX is a syntax extension. Either Typescript or Babel need to be used to compile JSX into a browser-friendly executable.

What is a React Fragment?

A common practice when returning multiple elements in a React Component is to wrap them together using a <div>. React Components require that all Components return only one element, and so this is the instinctual solution.

function DivExample() {
  return (
    <div>
      <h1>Welcome to Exponent!</h1>
      <h2>Learn the Top React Interview Questions!</h2>
    </div>
  );
}
notice the use of an additional div to return multiple jsx elements as one

However, React provides Fragments, essentially empty HTML tags <></>. These can wrap multiple elements while not actually rendering another div in the frontend, making much cleaner code.

function FragmentExample() {
  return (
    <>
      <h1>Welcome to Exponent!</h1>
      <h2>Learn the Top React Interview Questions!</h2>
    </>
  );
}
Notice here that an additional html element will not be rendered and the code appears more clean

What is render()?

Every React Class Component must have a render() this is the portion where UI is actually returned in the form of a single React element. These are not necessary in functional components, which simply returns the UI element. Class Components are quite common in older codebases, so be prepared to recognize the use of render().

Note, however, that whenever rendering any Component, only one React Element may be returned, and all JSX elements should be bundled under either a single div or a React Fragment.

What are refs in React?

Refs or References are an attribute in React where a reference to an element may be stored. In a sense, refs allow you to track elements in your UI, and manipulate them in some way, for instance by focusing on a text area.

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }
  render() {
    return <div ref={this.myRef} />;
  }
}

These too were often used in Class Components but can still be found in function components. The React documentation makes a point not to overuse refs, saying they should be used for the following reasons:

  • Managing focus, text selection, or media playback
  • Triggering imperative animations
  • Integrating with third-party DOM libraries

How is React different from Angular?

Angular is one of the primary competitors to React. Understanding the differences between these two is handy when being interviewed for a Front-End Developer role.

To start, Angular is a framework, providing a more rigid, but complete set of tools for creating a web application. This means the full Model-View-Controller architecture.

This differs from React providing only the View component of the MVC. Part of this also means Angular tends to be more involved with a steeper learning curve compared to React.

Additionally, React provides fundamental tools to make UI elements, essentially being very customizable while Angular has features to make more large-scale, interact-able applications.

Finally, a commonly noted difference between React and Angular is the lack of a virtual DOM within Angular to provide as-needed re-renders of UI elements.

What are some React Anti-patterns?

Understanding some React Anti-patterns help prevent yourself from falling into common traps as you review interview questions and answers.

Prop-Drilling

Prop-Drilling is a classic anti-pattern in React where a prop must originate very high up in a component tree, perhaps it's a state that is shared across many components, but the prop also needs to be passed through four or five components that have no use for it.

function Component1() {
  const [user, setUser] = useState("Exponent User");

  return (
    <>
      <h1>{`Hello ${user}!`}</h1>
      <Component2 user={user} />
    </>
  );
}

function Component2({ user }) {
  return (
    <>
      <h1>Component 2</h1>
      <Component3 user={user} />
    </>
  );
}

function Component3({ user }) {
  return (
    <>
      <h1>Component 3</h1>
      <Component4 user={user} />
    </>
  );
}

function Component4({ user }) {
  return (
    <>
      <h1>Component 4</h1>
      <Component5 user={user} />
    </>
  );
}

function Component5({ user }) {
  return (
    <>
      <h1>Component 5</h1>
      <h2>{`Hello ${user}`}</h2>
    </>
  );
}
Here there are four intermediate components that had to receive and pass a prop they had no use for

The biggest issue here is that several components have to include a prop that they don't themselves use. This can make tracking props exceedingly difficult, and quickly becomes hard to maintain as it's not immediately obvious why a prop is being passed to a certain component.

To avoid this, there are several solutions. Perhaps the simplest is the use of the Context API with the useContext() hook. Another solution could be the introduction of a library in the React ecosystem such as Redux or React Query.

Nested Components

Nested Components are a less obvious issue. This occurs when a component is declared using a function within another functional component.

function Parent() {

    function Child(){
    	return(<button>Go!</button>)
    }

  return (
    <div>
      <h1>Welcome to Exponent!</h1>
      <h2>Learn the Top React Interview Questions!</h2>
      <Child />
    </div>
  );
}
notice how the child component is fully nested inside the parent function

This may be tempting as the child component can be seen directly within the parent component, but because the child component would be re-created upon every update to the parent component, there will be performance issues.

To avoid this, simply create all components within their own function if not their own file for organizational purposes.

Repeating Complex Calculations

A more advanced anti-pattern. It's very easy to repeatedly perform memory-intensive calculations whenever a component is re-rendered. This can become a performance issue as often these calculations are done without any need.

To avoid this issue, simply use the useMemo() hook. This hook will "memoize" the result of a calculation and not perform the memory-intensive operation unless there would be some change to the output.

What are some React best practices?

Equally useful to Anti-patterns are best practices. The following patterns are some of the most common best practices and can very likely appear within an interview question.

Overall, best practices in development with React typically come down to the principle of DRY—Don't Repeat Yourself. Much of what's done in React can utilize Javascript so long, repetitive blocks of HTML are not needed.

Raise the State

One of the most common patterns in React is the need to lift up state. This is because sibling components often need to react to the same changes in State. Instead of creating state that works the same in two different components, simply raise the state to the nearest common parent.

This way, the state and the necessary setState property may be passed through props into any Component that may require access to this state.

Alternatively, the Context API and the useContext() hook may be utilized in cases to avoid prop drilling.

Make full use of Component reusability

In most any UI, there are several components that are repeated. When developing in React, it's important to break down Components and extract smaller components necessary.

The compartmentalization of components can make for a more maintainable, developer-friendly codebase. Additionally, the UI may become easier to handle through business logic and state when there are minimal UI elements within any given component.

Use map() to render Components

The Array.map() function in JavaScript is one of the best functions to use in conjunction with Components. This is because if data is received from an API in the form of an Array, that data can be quickly mapped through, creating a component for each datum using Array.map().

function MappedNumbers(props) {
  
  const data = props.data;  
  const listItems = numbers.map((datum) => <li>{datum}</li>  ); 
  
  return (
    <ul>{listItems}</ul>
  );
}
The component is taking the data from the props and making a jsx element for each datum, before returning it

This follows the principle of creating concise, minimal JavaScript code that maximizes the capabilities of JSX and React Components.

What are the limitations of React?

Whenever using a tool in the rapidly evolving world of Full-Stack Development, it's important to understand which limitations exist in any given tool. An interviewer may hope that you understand these limitations going in.

View, not Model-View-Controller

React is said to be a library, not a framework. It provides several tools to build UI elements, but it is much more minimal compared to full frameworks such as Angular or Django, which provide the entirety of an MVC architecture.

While the minimalism of React provides flexibility, this limitation should be considered when using React in a professional setting as a more complicated tech-stack will be needed.

Rapid Evolution of Technology

React is a tool that has evolved very rapidly over the past few years. Keeping up with changes is a necessary component of using the technology and represents an additional area of focus.

Only a few years ago, Class Components had once been the norm, and were the sole method of creating a stateful component. With React Hooks, Class Components suddenly became obsolete. A professional React developer must pay attention to such a change.

Lacking Documentation

React is often accompanied with several tools. Due to it being minimal, there are numerous tools that sprout up such as Redux, React Query, React Router etc. All of these are phenomenal tools.

But while an ecosystem of React-complementary tooling is a phenomenal asset, some of these libraries may contain very sparse or inaccurate documentation. This is especially true due to the aforementioned rapid evolution of React.

Search Engine Optimization

Something to consider with React is its Client-Side Rendering. This has been said to make SEO operations more difficult with how Google indexes dynamic websites.

Tags

Product Management Today