New 100 React Interview Questions

Table of Contents

Introduction

Are you preparing for a React interview and looking for a user-friendly introduction to common interview questions? Look no further! React is a popular JavaScript library used for building user interfaces. During interviews, you might encounter questions about React components, state management, lifecycle methods, and more. These questions aim to assess your understanding of React concepts and your ability to solve real-world problems. In this guide, we’ll provide concise and easy-to-understand explanations of commonly asked React interview questions, helping you prepare effectively and confidently for your upcoming interview. Let’s dive in and enhance your React knowledge!

Basic Questions

1. What is React?

React is a popular JavaScript library for building user interfaces. It allows developers to create reusable UI components and efficiently manage the state of the application. Here’s a simple example of a React component:

JSX
import React from 'react';

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}!</h1>;
  }
}

export default Welcome;

2. What are the main features of React?

The main features of React include:

  • Components and reusability
  • Virtual DOM for efficient rendering
  • JSX syntax for declarative UI
  • One-way data binding with props
  • State management
  • Lifecycle methods for control over component behavior
  • React Native for mobile app development

3. What is JSX?

JSX (JavaScript XML) is a syntax extension for React that allows you to write HTML-like code within JavaScript. It helps in creating React elements more intuitively. Here’s an example:

JSX
import React from 'react';

const element = <h1>Hello, JSX!</h1>;

export default element;

4. What is the difference between a Class component and a Functional component?

Class components are created using ES6 classes and have more features like state and lifecycle methods. Functional components, on the other hand, are simpler and mainly used for rendering UI based on props. Here’s a comparison:

Class Component example:

JSX
import React from 'react';

class Greeting extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}!</h1>;
  }
}

export default Greeting;

Functional Component example:

JSX
import React from 'react';

const Greeting = (props) => {
  return <h1>Hello, {props.name}!</h1>;
};

export default Greeting;

5. What is the virtual DOM?

The virtual DOM is a lightweight copy of the actual DOM maintained by React. It helps improve rendering performance by minimizing direct manipulation of the real DOM. Here’s an example of how it works:

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

// Instead of directly rendering to the real DOM, React renders to the virtual DOM first
const virtualElement = <h1>Hello, Virtual DOM!</h1>;

// Then, React compares the virtual DOM with the actual DOM and performs only necessary updates
ReactDOM.render(virtualElement, document.getElementById('root'));

6. What is the role of ReactDOM.render() in React?

ReactDOM.render() is used to render React elements to the real DOM. It takes a React element and attaches it to a specific HTML element in the document. Here’s an example:

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

const element = <h1>Hello, ReactDOM!</h1>;

ReactDOM.render(element, document.getElementById('root'));

7. What is a React component?

A React component is a reusable piece of UI that can have its own state and properties (props). It can be a class component or a functional component. Here’s an example:

JSX
import React from 'react';

class Button extends React.Component {
  render() {
    return <button>{this.props.label}</button>;
  }
}

export default Button;

8. How do you create a component in React?

In React, you can create a component by defining a class or a function. Here’s an example of both class and functional components:

Class Component example:

JSX
import React from 'react';

class Greeting extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}!</h1>;
  }
}

export default Greeting;

Functional Component example:

JSX
import React from 'react';

const Greeting = (props) => {
  return <h1>Hello, {props.name}!</h1>;
};

export default Greeting;

9. What is state in React?

State is a mechanism to store and manage data within a React component. It allows components to change and re-render based on changes to the data. Here’s an example of using state in a class component:

JSX
import React from 'react';

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

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

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.increment}>Increment</button>
      </div>
    );
  }
}

export default Counter;

10. What are props in React?

Props (short for properties) are used to pass data from a parent component to a child component. They are immutable and help to make components more dynamic and reusable. Here’s an example:

JSX
import React from 'react';

const Greeting = (props) => {
  return <h1>Hello, {props.name}!</h1>;
};

export default Greeting;

Usage of the component:

JSX
import React from 'react';
import Greeting from './Greeting';

const App = () => {
  return <Greeting name="John" />;
};

export default App;

11. What is the difference between state and props?

FeatureStateProps
MutabilityCan be changed within the component using setStateImmutable and passed from parent component
UsageUsed for managing internal component dataUsed for passing data from parent to child component
Owned byOwned and managed by the componentOwned and managed by the parent component
ModificationCan be modified by the component itselfCannot be modified by the component, read-only
Update triggersChanges in state trigger a re-render of the componentChanges in props trigger a re-render of the component
ExampleSee the state example in the previous questionSee the props example in the previous question

12. What are the React lifecycle methods?

React lifecycle methods allow you to hook into specific moments during the lifecycle of a component. Here are some of the commonly used lifecycle methods:

JSX
import React from 'react';

class LifecycleDemo extends React.Component {
  constructor() {
    super();
    console.log('Constructor called.');
  }

  componentDidMount() {
    console.log('Component did mount.');
  }

  componentDidUpdate() {
    console.log('Component did update.');
  }

  componentWillUnmount() {
    console.log('Component will unmount.');
  }

  render() {
    console.log('Render called.');
    return <h1>Hello, Lifecycle!</h1>;
  }
}

export default LifecycleDemo;

13. What is the purpose of super() in React?

In React class components, super() is used to call the constructor of the parent class (i.e., React.Component). It is necessary to call super() if you define a constructor in a subclass to properly initialize the component.

JSX
import React from 'react';

class ChildComponent extends React.Component {
  constructor() {
    super(); // Call to the parent class constructor
    // Other component-specific initialization here
  }

  render() {
    return <h1>Hello, I'm the child component!</h1>;
  }
}

export default ChildComponent;

14. What is the purpose of render() in React?

The render() method is a required lifecycle method in a React class component. It returns the JSX or React elements that make up the UI of the component.

JSX
import React from 'react';

class Greeting extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}!</h1>;
  }
}

export default Greeting;

15. What is a Steady Component? Give a relevant code example.

I’m not aware of the term “Steady Component” in the context of React. It might be an obsolete term or a term used in a specific context not covered in my training data.

16. What is an Uncontrolled Component?

An Uncontrolled Component is a form element (like input, textarea, etc.) that manages its own state internally rather than being controlled by React’s state. It typically uses a ref to access its current value.

JSX
import React from 'react';

class UncontrolledForm extends React.Component {
  inputRef = React.createRef();

  handleSubmit = (event) => {
    event.preventDefault();
    console.log('Submitted value:', this.inputRef.current.value);
  };

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <input type="text" ref={this.inputRef} />
        <button type="submit">Submit</button>
      </form>
    );
  }
}

export default UncontrolledForm;

17. What is the use of keys in React?

Keys in React are used to help identify individual elements in a list. They aid React in efficiently updating and reordering elements without re-rendering all of them. Keys should be unique within the list.

JSX
import React from 'react';

const TodoList = () => {
  const todos = [
    { id: 1, text: 'Buy groceries' },
    { id: 2, text: 'Walk the dog' },
    { id: 3, text: 'Clean the house' },
  ];

  return (
    <ul>
      {todos.map((todo) => (
        <li key={todo.id}>{todo.text}</li>
      ))}
    </ul>
  );
};

export default TodoList;

18. What is a higher order component?

A Higher Order Component (HOC) is a pattern in React where a function takes a component and returns a new component with additional props or behavior.

JSX
import React from 'react';

const withTitle = (WrappedComponent, title) => {
  return (props) => (
    <>
      <h1>{title}</h1>
      <WrappedComponent {...props} />
    </>
  );
};

const Greeting = (props) => {
  return <p>Hello, {props.name}!</p>;
};

const GreetingWithTitle = withTitle(Greeting, 'Welcome');

export default GreetingWithTitle;

19. What is a fragment in React?

A Fragment is a built-in component in React that allows you to group multiple elements without adding an additional DOM element to the output.

JSX
import React from 'react';

const MyFragment = () => {
  return (
    <>
      <h1>Title</h1>
      <p>Paragraph 1</p>
      <p>Paragraph 2</p>
    </>
  );
};

export default MyFragment;

20. What is Context API in React?

The Context API in React allows you to pass data down the component tree without explicitly passing it through props at every level. It is useful when data needs to be accessed by many components at different nesting levels.

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

// Create a context
const MyContext = createContext();

// Provide data using the context provider
const App = () => {
  return (
    <MyContext.Provider value="Hello from Context">
      <ChildComponent />
    </MyContext.Provider>
  );
};

// Consume data from the context
const ChildComponent = () => {
  const dataFromContext = useContext(MyContext);
  return <p>{dataFromContext}</p>;
};

export default App;

21. What are hooks in React?

Hooks are functions that allow you to use React features like state and lifecycle methods in functional components. Some commonly used hooks include useState, useEffect, useContext, etc.

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

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

  const increment = () => {
    setCount((prevCount) => prevCount + 1);
  };

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

export default Counter;

22. What is the use of useEffect in React?

The useEffect hook in React is used to perform side effects in functional components, such as data fetching, subscriptions, or manual DOM manipulation. It runs after every render of the component.

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

const DataFetching = () => {
  const [data, setData] = useState([]);

  useEffect(() => {
    // Simulating data fetching with setTimeout
    const fetchData = () => {
      setTimeout(() => {
        setData(['Item 1', 'Item 2', 'Item 3']);
      }, 1000);
    };

    fetchData();
  }, []);

  return (
    <ul>
      {data.map((item, index) => (
        <li key={index}>{item}</li>
      ))}
    </ul>
  );
};

export default DataFetching;

23. How to apply validation on props in React?

You can use the prop-types library to apply validation on props in React. It helps to define the expected type and presence of props.

JSX
import React from 'react';
import PropTypes from 'prop-types';

const Greeting = (props) => {
  return <h1>Hello, {props.name}!</h1>;
};

Greeting.propTypes = {
  name: PropTypes.string.isRequired,
};

export default Greeting;

24. What is the use of React Router?

React Router is a library that allows you to handle routing and navigation in a React application. It helps in creating Single Page Applications (SPAs)

by rendering different components based on the URL.

JSX
import React from 'react';
import { BrowserRouter as Router, Switch, Route, Link } from 'react-router-dom';

const Home = () => <h1>Welcome to the Home page!</h1>;
const About = () => <h1>About Us</h1>;
const Contact = () => <h1>Contact Us</h1>;

const App = () => {
  return (
    <Router>
      <nav>
        <ul>
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/about">About</Link>
          </li>
          <li>
            <Link to="/contact">Contact</Link>
          </li>
        </ul>
      </nav>
      <Switch>
        <Route exact path="/" component={Home} />
        <Route path="/about" component={About} />
        <Route path="/contact" component={Contact} />
      </Switch>
    </Router>
  );
};

export default App;

25. What are synthetic events in React?

Synthetic events in React are synthetic wrappers around the native browser events. They provide cross-browser compatibility and automatic event pooling.

JSX
import React from 'react';

const Button = () => {
  const handleClick = (event) => {
    console.log('Button clicked!', event.target.value);
  };

  return <button onClick={handleClick}>Click Me</button>;
};

export default Button;

26. How to conditionally render components in React?

You can use conditional statements like if-else or ternary operators to conditionally render components in React.

Using if-else:

JSX
import React from 'react';

const ConditionalComponent = ({ showComponent }) => {
  if (showComponent) {
    return <h1>Show this component!</h1>;
  } else {
    return <h1>Don't show this component!</h1>;
  }
};

export default ConditionalComponent;

Using ternary operator:

JSX
import React from 'react';

const ConditionalComponent = ({ showComponent }) => {
  return showComponent ? <h1>Show this component!</h1> : <h1>Don't show this component!</h1>;
};

export default ConditionalComponent;

27. What is ‘Lifting State Up’ in React?

‘Lifting State Up’ is the process of moving the state from a child component to its parent component when multiple child components need to share the same state.

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

const ChildComponent = ({ count, increment }) => {
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
};

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

  const increment = () => {
    setCount((prevCount) => prevCount + 1);
  };

  return <ChildComponent count={count} increment={increment} />;
};

export default ParentComponent;

28. How can you handle events in React?

In React, you can handle events by passing event handlers as props to the components.

JSX
import React from 'react';

const Button = ({ onClick }) => {
  return <button onClick={onClick}>Click Me</button>;
};

const App = () => {
  const handleClick = () => {
    console.log('Button clicked!');
  };

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

export default App;

29. What is the use of refs in React?

Refs in React are used to get direct access to a DOM element or a component instance. They should be used sparingly, as they bypass React’s usual data flow.

JSX
import React, { useRef } from 'react';

const InputComponent = () => {
  const inputRef = useRef();

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

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

export default InputComponent;

30. What are the limitations of React?

Some of the limitations of React include:

  • Steeper learning curve for beginners due to the concepts of components and state management.
  • React focuses on the view layer of the application, and developers may need to use additional libraries for complex state management and routing.
  • Large React applications can face performance issues, and optimization might be needed.
  • Using React for SEO can be challenging due to server-side rendering requirements.
  • React Native, while great for cross-platform mobile apps, may have limitations in accessing certain native device functionalities compared to native development.

Intermediate Questions

1. What is the React Context API and how is it used?

The React Context API is used to manage global state in React applications without having to pass props through all levels of the component tree. It allows data to be shared and accessed by any component within a specific context.

Example:

JSX
// Create a context
const MyContext = React.createContext();

// Create a provider component to wrap around components that need access to the context data
function MyProvider({ children }) {
  const sharedData = "This is the shared data.";

  return (
    <MyContext.Provider value={sharedData}>
      {children}
    </MyContext.Provider>
  );
}

// A component that consumes data from the context
function MyComponent() {
  const data = useContext(MyContext);

  return <div>{data}</div>;
}

// Wrap the components that need access to the context data with the provider
function App() {
  return (
    <MyProvider>
      <MyComponent />
    </MyProvider>
  );
}

2. What are Pure Components in React?

Pure Components are a type of React component that automatically implements a shallow comparison of their props and state to determine if a re-render is necessary. They can help improve performance by avoiding unnecessary re-renders.

Example:

JSX
// Regular Component
class RegularComponent extends React.Component {
  render() {
    return <div>{this.props.name}</div>;
  }
}

// Pure Component
class PureComponentExample extends React.PureComponent {
  render() {
    return <div>{this.props.name}</div>;
  }
}

3. What is a higher-order component (HOC)? Can you provide an example?

A Higher-Order Component (HOC) is a function that takes a component and returns a new component with extended functionality. HOCs are used for code reuse, logic sharing, and adding additional props to components.

Example:

JSX
// Higher-Order Component
function withLogger(WrappedComponent) {
  return class extends React.Component {
    componentDidMount() {
      console.log("Component was mounted.");
    }

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

// Component to be wrapped with the HOC
class MyComponent extends React.Component {
  render() {
    return <div>Hello, {this.props.name}</div>;
  }
}

// Wrap the component with the HOC
const MyComponentWithLogger = withLogger(MyComponent);

// Render the wrapped component
function App() {
  return <MyComponentWithLogger name="John" />;
}

4. Explain the concept of “Lifting State Up” in React.

“Lifting State Up” is a pattern in React where state is moved from a child component to its parent component, so multiple child components can share and modify the same state.

Example:

JSX
// Child component
function TemperatureInput(props) {
  return (
    <input
      type="number"
      value={props.temperature}
      onChange={(e) => props.onTemperatureChange(e.target.value)}
    />
  );
}

// Parent component
class Calculator extends React.Component {
  constructor(props) {
    super(props);
    this.state = { temperature: 0 };
  }

  handleTemperatureChange = (temperature) => {
    this.setState({ temperature });
  };

  render() {
    const { temperature } = this.state;
    return (
      <div>
        <TemperatureInput
          temperature={temperature}
          onTemperatureChange={this.handleTemperatureChange}
        />
        <TemperatureInput
          temperature={temperature}
          onTemperatureChange={this.handleTemperatureChange}
        />
      </div>
    );
  }
}

In this example, the Calculator component lifts the temperature state up from the TemperatureInput components, allowing both inputs to share and update the same state.

5. How do you handle forms in React?

In React, you can handle forms using controlled components. Controlled components tie the form elements to the component state, allowing React to control the form’s values.

Example:

JSX
class LoginForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      username: '',
      password: ''
    };
  }

  handleInputChange = (e) => {
    const { name, value } = e.target;
    this.setState({ [name]: value });
  };

  handleSubmit = (e) => {
    e.preventDefault();
    // Perform form submission logic here
    console.log("Submitted data:", this.state);
  };

  render() {
    const { username, password } = this.state;
    return (
      <form onSubmit={this.handleSubmit}>
        <input
          type="text"
          name="username"
          value={username}
          onChange={this.handleInputChange}
        />
        <input
          type="password"
          name="password"
          value={password}
          onChange={this.handleInputChange}
        />
        <button type="submit">Login</button>
      </form>
    );
  }
}

6. How do you implement Error Boundaries in React for error handling?

Error Boundaries in React are components that catch JavaScript errors during rendering, in lifecycle methods, and during the constructor execution of the whole tree below them. They help prevent the entire application from crashing due to a single component error.

Example:

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

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

  componentDidCatch(error, errorInfo) {
    // Log the error or send it to an error reporting service
    console.error("Error caught by ErrorBoundary:", error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      return <div>Something went wrong!</div>;
    }

    return this.props.children;
  }
}

// Usage of ErrorBoundary
function App() {
  return (
    <ErrorBoundary>
      <ComponentThatMightThrowAnError />
    </ErrorBoundary>
  );
}

7. Explain the use of arrow functions in React.

Arrow functions in React are used for defining concise and inline function expressions. They automatically bind the value of this based on the surrounding context and help avoid common pitfalls with this keyword scoping.

Example:

JSX
// Regular function component
function MyComponent() {
  return (
    <button onClick={function() { console.log("Clicked!"); }}>
      Click Me
    </button>
  );
}

// Using arrow function
function MyComponent() {
  return (
    <button onClick={() => { console.log("Clicked!"); }}>
      Click Me
    </button>
  );
}

In the above example, the arrow function does not need to explicitly bind this because it automatically inherits the surrounding context, whereas the regular function would require explicit binding or it would not work as expected.

8. What is Redux and how is it related to React?

Redux is a predictable state container for JavaScript applications. It is often used with React to manage the state of an application and provide a centralized store that holds the application state.

Example:

JSX
// Redux store setup
import { createStore } from 'redux';

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

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

// React component using Redux
import { useSelector, useDispatch } from 'react-redux';

function Counter() {
  const count = useSelector(state => state.count);
  const dispatch = useDispatch();

  return (
    <div>
      <span>Count: {count}</span>
      <button onClick={() => dispatch({ type: 'INCREMENT' })}>Increment</button>
      <button onClick={() => dispatch({ type: 'DECREMENT' })}>Decrement</button>
    </div>
  );
}

In the above example, the Redux store is set up with a reducer function that handles state changes based on dispatched actions. The Counter component uses Redux hooks (useSelector and useDispatch) to access the state from the store and dispatch actions to update the state.

9. What is the significance of Store in Redux?

The Store in Redux is a single source of truth that holds the state of the entire application. It plays a crucial role in managing the application state and ensuring that the state is updated in a predictable manner. The store helps to:

  • Hold the application state in one place, making it easy to access and manage the state from any component.
  • Provide a mechanism to subscribe to state changes, enabling components to react to changes in the state.
  • Dispatch actions to modify the state in a controlled and predictable way through reducers.

10. What is a reducer in Redux?

In Redux, a reducer is a pure function that takes the current state and an action as arguments and returns a new state based on that action. It specifies how the state should change in response to the action dispatched to the Redux store.

Example:

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

In this example, counterReducer takes the state and an action as arguments and returns a new state based on the action type. When the action type is 'INCREMENT', the count is increased by 1, and when the action type is 'DECREMENT', the count is decreased by 1.

11. Explain how Redux Thunk works.

Redux Thunk is a middleware that allows asynchronous actions to be dispatched in Redux. It extends the capabilities of Redux to handle asynchronous operations such as making API calls before dispatching an action.

Example:

JSX
// Redux Thunk action creator
function fetchData() {
  return (dispatch) => {
    dispatch({ type: 'FETCH_DATA_START' });

    // Simulate an API call
    setTimeout(() => {
      const data = [1, 2, 3, 4];
      dispatch({ type: 'FETCH_DATA_SUCCESS', payload: data });
    }, 1000);
  };
}

// Usage of the thunk action creator
import { useDispatch, useSelector } from 'react-redux';

function MyComponent() {
  const dispatch = useDispatch();
  const data = useSelector((state) => state.data);

  const handleFetchData = () => {
    dispatch(fetchData());
  };

  return (
    <div>
      <button onClick={handleFetchData}>Fetch Data</button>
      <ul>
        {data.map((item) => (
          <li key={item}>{item}</li>
        ))}
      </ul>
    </div>
  );
}

In this example, the fetchData action creator returns a function instead of a plain object. Redux Thunk intercepts this function and provides the dispatch method as an argument. This allows the function to perform asynchronous operations and dispatch multiple actions at different times.

12. How would you handle asynchronous actions in Redux?

Asynchronous actions in Redux can be handled using Redux Thunk or other middleware libraries like Redux Saga or Redux Observable. Here’s an example using Redux Thunk:

JSX
// Redux Thunk action creator
function fetchData() {
  return async (dispatch) => {
    dispatch({ type: 'FETCH_DATA_START' });

    try {
      // Simulate an API call
      const response = await fetch('https://api.example.com/data');
      const data = await response.json();

      dispatch({ type: 'FETCH_DATA_SUCCESS', payload: data });
    } catch (error) {
      dispatch({ type: 'FETCH_DATA_ERROR', payload: error.message });
    }
  };
}

// Usage of the thunk action creator
import { useDispatch, useSelector } from 'react-redux';

function MyComponent() {
  const dispatch = useDispatch();
  const data = useSelector((state) => state.data);
  const error = useSelector((state) => state.error);

  const handleFetchData = () => {
    dispatch(fetchData());
  };

  return (
    <div>
      <button onClick={handleFetchData}>Fetch Data</button>
      {data ? (
        <ul>
          {data.map((item) => (
            <li key={item}>{item}</li>
          ))}
        </ul>
      ) : (
        <p>{error || 'No data available.'}</p>
      )}
    </div>
  );
}

In this example, the fetchData action creator uses async/await to handle the asynchronous API call. It dispatches different actions based on the success or failure of the API call.

13. What are the middleware functions in Redux?

Middleware functions in Redux provide a way to extend the behavior of dispatch and allow additional processing to be done before an action reaches the reducer. Middleware sits between the action being dispatched and reaching the reducer.

Example using custom middleware:

JSX
// Custom middleware
const loggerMiddleware = (store) => (next) => (action) => {
  console.log('Dispatching action:', action);
  const result = next(action);
  console.log('Updated state:', store.getState());
  return result;
};

// Applying the middleware to the Redux store
import { createStore, applyMiddleware } from 'redux';
import rootReducer from './reducers';

const store =

 createStore(rootReducer, applyMiddleware(loggerMiddleware));

In this example, the loggerMiddleware logs the dispatched action and the updated state after every action. The applyMiddleware function is used to include this middleware when creating the Redux store.

14. How do you make use of the ‘connect’ function in Redux?

The connect function from react-redux library is used to connect a React component to the Redux store. It allows the component to access the state and dispatch actions as props.

Example:

JSX
import { connect } from 'react-redux';

// Component
function MyComponent(props) {
  return <div>Count: {props.count}</div>;
}

// mapStateToProps function
const mapStateToProps = (state) => {
  return {
    count: state.count
  };
};

// Connect the component to the Redux store
const ConnectedComponent = connect(mapStateToProps)(MyComponent);

// Usage of the connected component
function App() {
  return <ConnectedComponent />;
}

In this example, the mapStateToProps function specifies which parts of the state should be mapped to the component’s props. The connect function connects the component to the Redux store and makes the count state available as a prop in the MyComponent.

15. What is the purpose of ‘mapStateToProps’ and ‘mapDispatchToProps’ in Redux?

  • mapStateToProps: It is a function used in connect to specify which parts of the Redux state should be mapped to the component’s props. It is used to extract data from the Redux store’s state and pass it as props to the component.

Example:

JSX
const mapStateToProps = (state) => {
  return {
    count: state.count
  };
};
  • mapDispatchToProps: It is a function used in connect to specify which action creators from Redux should be mapped to the component’s props. It is used to pass action creators as props to the component, making it easy to dispatch actions from the component.

Example:

JSX
const mapDispatchToProps = (dispatch) => {
  return {
    increment: () => dispatch({ type: 'INCREMENT' }),
    decrement: () => dispatch({ type: 'DECREMENT' })
  };
};

In the above example, the increment and decrement action creators are mapped to the component’s props using mapDispatchToProps, allowing the component to dispatch these actions.

16. How do you implement routing in React?

Routing in React can be implemented using libraries like React Router. React Router provides components that help you define different routes in your application and navigate between them.

Example using React Router:

JSX
// Installation: npm install react-router-dom

// App.js
import { BrowserRouter as Router, Switch, Route, Link } from 'react-router-dom';

function Home() {
  return <div>Welcome to the Home page!</div>;
}

function About() {
  return <div>This is the About page.</div>;
}

function Contact() {
  return <div>Contact us at example@example.com</div>;
}

function App() {
  return (
    <Router>
      <nav>
        <ul>
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/about">About</Link>
          </li>
          <li>
            <Link to="/contact">Contact</Link>
          </li>
        </ul>
      </nav>
      <Switch>
        <Route exact path="/" component={Home} />
        <Route path="/about" component={About} />
        <Route path="/contact" component={Contact} />
      </Switch>
    </Router>
  );
}

In this example, we use BrowserRouter as the router implementation and set up different routes using Route components. The Switch component ensures that only the first matched route is rendered, preventing multiple components from being shown simultaneously.

17. What is the difference between ‘react-router’ and ‘react-router-dom’?

react-routerreact-router-dom
Core package for React Router, containing the routing logic.Contains DOM bindings specific to React Router for web apps.
Typically used for routing in non-web environments (e.g., React Native).Designed for web applications and includes BrowserRouter.
Doesn’t provide BrowserRouter or other DOM-specific components.Includes components like BrowserRouter, Link, etc.

Both packages work together, but react-router-dom is the more commonly used package for web applications.

18. What is a render prop?

A render prop is a pattern in React where a component receives a function as a prop, and that function is responsible for rendering content. It allows the parent component to share its internal state or logic with the child component.

Example:

JSX
// Parent component with a render prop
class MouseTracker extends React.Component {
  render() {
    return (
      <div onMouseMove={(e) => this.props.render(e)}>
        {/* Some other content */}
      </div>
    );
  }
}

// Usage of the MouseTracker component with a render prop
function App() {
  return (
    <MouseTracker
      render={(e) => <div>Mouse position: {e.clientX}, {e.clientY}</div>}
    />
  );
}

In this example, the MouseTracker component takes a render prop, which is a function that receives the mouse event and returns JSX to be rendered. The App component uses the MouseTracker and defines how the mouse position is displayed.

19. What is a controlled component in React?

A controlled component in React is a component where the form data and its behavior are controlled by React. The component receives its current value and onChange event handler through props and notifies the parent component about any changes.

Example:

JSX
class InputForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = { inputValue: '' };
  }

  handleInputChange = (e) => {
    this.setState({ inputValue: e.target.value });
  };

  handleSubmit = (e) => {
    e.preventDefault();
    // Submit the form data
    console.log("Submitted value:", this.state.inputValue);
  };

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <input
          type="text"
          value={this.state.inputValue}
          onChange={this.handleInputChange}
        />
        <button type="submit">Submit</button>
      </form>
    );
  }
}

In this example, the InputForm component is a controlled component because the value of the input field is controlled by the component’s state and changes to the input value are handled through the handleInputChange method.

20. What are hooks in React?

Hooks are functions in React that allow you to use state and other React features in functional components. They were introduced in React 16.8 to provide a simpler and more concise way to work with stateful logic in functional components.

Example:

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

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

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

  const decrement = () => {
    setCount(count - 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
    </div>
  );
}

In this example, the useState hook allows us to add state to a functional component. The count and setCount variables are used to store and update the state, and the component’s UI reflects the current state.

21. Explain the use of the useEffect hook in React.

The useEffect hook in React is used to perform side effects in functional components. It is similar to lifecycle methods like componentDidMount, componentDidUpdate, and componentWillUnmount.

Example:

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

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

  useEffect(() => {
    // Fetch data from an API
    fetch('https://api.example.com/data')
      .then((response) => response.json())
      .then((data) => setData(data))
      .catch((error) => console.error('Error fetching data:', error));
  }, []); // Empty dependency array means the effect runs only once (on mount)

  return (
    <ul>
      {data.map((item) => (
        <li key={item.id}>{item.name}</li>
      ))}
    </ul>
  );
}

In this example, the useEffect hook is used to fetch data from an API when the component mounts. The effect is set to run only once, as the dependency array is empty ([]). If you provide a non-empty dependency array, the effect will run whenever the dependencies change.

22. What is the useState hook in React?

The useState hook is used to add state to functional components in React. It returns a pair of values: the current state and a function to update that state.

Example:

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

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

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

  const decrement = () => {
    setCount(count - 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
    </div>
  );
}

In this example, the useState hook is used to create a count state variable with an initial value of 0. The setCount function is used to update the value of count when the buttons are clicked.

23. What are React PropTypes and how do you use them?

React PropTypes are used for type checking the props passed to a component. They help to ensure that the correct data types are being passed to components, which can prevent potential bugs and improve code maintainability.

Example:

JSX
import PropTypes from 'prop-types';

function Greeting(props) {
  return <div>Hello, {props.name}</div>;
}

Greeting.propTypes = {
  name: PropTypes.string.isRequired
};

In this example, the propTypes property is used to define the expected types and constraints for the name prop of the Greeting component. In this case, name should be a string and is required (marked with isRequired). If the prop is missing or of the wrong type, a warning will be shown in the console during development.

24. What are Synthetic Events in React?

Synthetic Events in React are a cross-browser wrapper around the browser’s native events. They are similar to native events but provide consistent behavior across different browsers.

Example:

JSX
function Button() {
  const handleClick = (e) => {
    e.preventDefault();
    console.log('Button clicked!');
  };

  return (
    <button onClick={handleClick}>Click Me</button>
  );
}

In this example, the onClick event is a synthetic event provided by React. The handleClick function is called when the button is clicked, and e.preventDefault() prevents the default behavior of the event (e.g., form submission or link navigation).

25. Explain the lifecycle methods in React Components.

React class components have several lifecycle methods that allow you to hook into the different phases of a component’s life. These methods can be used for performing actions at specific points in the component’s lifecycle.

Here are the main lifecycle methods:

  1. componentDidMount: This method is called after the component has been rendered to the screen. It is commonly used for making AJAX requests or setting up subscriptions.
  2. componentDidUpdate: This method is called whenever the component is updated or re-rendered. It can be used for performing actions after an update, such as updating the DOM based on new data.
  3. componentWillUnmount: This method is called just before the component is removed from the DOM. It can be used for cleanup, such as removing event listeners or canceling subscriptions.
  4. shouldComponentUpdate: This method allows you to control whether the component should re-render or not. By default, the component re-renders whenever its state or props change, but you can implement this method to optimize performance by preventing unnecessary re-renders.
  5. getDerivedStateFromProps: This static method is called before rendering and is used to update the state based on changes in props. It is rarely used, as you should prefer using controlled components.

26. How do you implement server-side rendering or isomorphic rendering in React?

Server-side rendering (SSR) or isomorphic rendering in React means rendering the initial page content on the server before sending it to the client. It can improve the initial load time and SEO of the application.

Example using Node.js and Express:

JSX
// server.js
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import App from './App';

import express from 'express';
const app = express();

app.get('/', (req, res) => {
  const html = ReactDOMServer.renderToString(<App />);
  res.send(`
    <html>
      <head>
        <title>My React App</title>
      </head>
      <body>
        <div id="root">${html}</div>
      </body>
    </html>
  `);
});

app.listen(3000, () => {
  console.log('Server is running on http://localhost:3000');
});

In this example, we use ReactDOMServer.renderToString to render the ReactApp component to a string on the server. The server responds with the generated HTML containing the initial content of the React app.

27. What is the significance of keys in React lists?

Keys are a special attribute used in React when rendering lists of elements. They help React identify which items have changed, been added, or been removed from the list. When a list is re-rendered, React uses keys to efficiently update the DOM, minimizing unnecessary DOM manipulations and improving performance.

Example:

JSX
function ListComponent() {
  const items = ['Item 1', 'Item 2', 'Item 3'];

  return (
    <ul>
      {items.map((item, index) => (
        <li key={index}>{item}</li>
      ))}
    </ul>
  );
}

In this example, each list item is given a unique key based on its index. If the order of the list changes, or an item is added or removed, React can identify which elements need to be updated, moved, or inserted based on their keys.

28. Explain how to do code-splitting in React.

Code-splitting is a technique in React that allows you to split your bundled JavaScript code into smaller chunks, which can be loaded on-demand. This can help reduce the initial loading time of the application.

Example using dynamic import (available in modern environments with native dynamic import support or using a tool like Webpack):

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

const LazyComponent = React.lazy(() => import('./LazyComponent'));

function App() {
  const [showLazyComponent, setShowLazyComponent] = useState(false);

  const handleClick = () => {
    setShowLazyComponent(true);
  };

  return (
    <div>
      <button onClick={handleClick}>Load Lazy Component</button>
      {showLazyComponent && (
        <React.Suspense fallback={<div>Loading...</div>}>
          <LazyComponent />
        </React.Suspense>
      )}
    </div>
  );
}

In this example, we use React.lazy to dynamically import the LazyComponent when the button is clicked. The React.Suspense component is used to show a fallback while the component is being loaded.

29. What are the benefits of using React.memo()?

React.memo() is a higher-order component provided by React to optimize functional components by preventing unnecessary re-renders. When you wrap a component with React.memo(), it will only re-render when its props change.

Benefits of using React.memo():

  1. Performance improvement: It reduces re-renders for components that receive the same props, improving the application’s performance.
  2. Reduction in unnecessary calculations: Components wrapped in React.memo() avoid unnecessary calculations in the render function when their props haven’t changed.
  3. Easy to use: It is easy to implement; you just wrap your functional component with React.memo().

Example:

JSX
import React from 'react';

const MemoizedComponent = React.memo(MyComponent);

In this example, MyComponent will be memoized, and it will only re-render when its props change.

30. How can you optimize a React application’s performance?

To optimize a React application’s performance, you can follow these practices:

  1. Use functional components and hooks: Functional components have better performance than class components. Hooks, like useState, useEffect, and useMemo, allow you to optimize the component’s behavior and reduce unnecessary re-renders.
  2. Use React.memo(): As mentioned earlier, React.memo() helps prevent unnecessary re-renders for functional components by caching the result of the component’s rendering.
  3. Code-splitting: Use code-splitting techniques to load only the required parts of the application when needed. This can reduce the initial loading time of the application.
  4. Use shouldComponentUpdate or React.memo() with custom comparison functions: In class components, you can use shouldComponentUpdate to prevent unnecessary renders. With functional components, you can use React.memo() and provide a custom comparison function to control when the component should re-render.
  5. Optimize list rendering: When rendering lists, use unique keys for each item to optimize updates. Avoid using the index as the key if the list items can be reordered.
  6. Use production build: Make sure to use the production build of React for your production environment. It includes performance optimizations and removes development-only features.
  7. Profiling: Use React’s built-in profiler or third-party tools to identify performance bottlenecks in your application and optimize them.
  8. Optimize images and assets: Compress images and other assets to reduce their size and improve the application’s loading time.
  9. Use memoization and caching: Use memoization techniques, like useMemo or memoization libraries, to cache the results of expensive computations and avoid redundant calculations.
  10. Avoid unnecessary state updates: Make sure to update the state only when necessary, and use functional updates when modifying the state based on its previous value.

Advanced Questions

1. What is reconciliation in React?

Reconciliation is the process in React where the virtual DOM is compared to the actual DOM and any differences are updated efficiently to minimize unnecessary DOM manipulations. This process helps improve performance by reducing the number of updates needed to keep the UI in sync.

Example:

JSX
// Initial state
const data = ['Item 1', 'Item 2', 'Item 3'];

// Initial rendering
const element = (
  <ul>
    {data.map((item) => (
      <li key={item}>{item}</li>
    ))}
  </ul>
);

ReactDOM.render(element, document.getElementById('root'));

// Updated state
const updatedData = ['Item 1', 'Item 3', 'Item 4'];

// Updated rendering
const updatedElement = (
  <ul>
    {updatedData.map((item) => (
      <li key={item}>{item}</li>
    ))}
  </ul>
);

// React performs reconciliation and efficiently updates only the necessary changes in the actual DOM
ReactDOM.render(updatedElement, document.getElementById('root'));

2. What is the Flux architecture? How is it different from Redux?

Flux is a design pattern for managing application state in a predictable way. It has four major components: Actions, Dispatcher, Stores, and Views (React components). Flux emphasizes unidirectional data flow, where data changes flow in a single direction from Actions through the Dispatcher to the Stores, and then to the Views.

Redux is a state management library inspired by Flux but simplifies the architecture by having a single store instead of multiple stores. Redux also emphasizes immutability and a pure reducer function to update state.

Example of Flux (simplified version):

JSX
// Action
const ActionTypes = {
  UPDATE_DATA: 'UPDATE_DATA',
};

const updateDataAction = (data) => ({
  type: ActionTypes.UPDATE_DATA,
  payload: data,
});

// Dispatcher
class Dispatcher {
  constructor() {
    this.callbacks = [];
  }

  register(callback) {
    this.callbacks.push(callback);
  }

  dispatch(action) {
    this.callbacks.forEach((callback) => callback(action));
  }
}

const dispatcher = new Dispatcher();

// Store
let data = [];

const dataStore = (state = data, action) => {
  switch (action.type) {
    case ActionTypes.UPDATE_DATA:
      return action.payload;
    default:
      return state;
  }
};

// View
const renderView = (data) => {
  // Render the view using the updated data
};

// Subscribe to store changes
dispatcher.register((action) => {
  data = dataStore(data, action);
  renderView(data);
});

// Initial dispatch to update data
dispatcher.dispatch(updateDataAction(['Item 1', 'Item 2']));

Example of Redux (simplified version):

JSX
import { createStore } from 'redux';

// Action
const ActionTypes = {
  UPDATE_DATA: 'UPDATE_DATA',
};

const updateDataAction = (data) => ({
  type: ActionTypes.UPDATE_DATA,
  payload: data,
});

// Reducer
const dataReducer = (state = [], action) => {
  switch (action.type) {
    case ActionTypes.UPDATE_DATA:
      return action.payload;
    default:
      return state;
  }
};

// Store
const store = createStore(dataReducer);

// View
const renderView = () => {
  const data = store.getState();
  // Render the view using the updated data
};

// Subscribe to store changes
const unsubscribe = store.subscribe(renderView);

// Initial dispatch to update data
store.dispatch(updateDataAction(['Item 1', 'Item 2']));

3. Can you explain the concept of “Immutable State”?

Immutable state means that the state object cannot be modified directly after it’s created. Instead of mutating the state, you create a new state object with the required changes. This concept is important because it helps avoid unwanted side effects and makes it easier to track changes in the application.

Example:

JSX
import { useState } from 'react';

// Incorrect mutable state update
const mutableStateExample = () => {
  const [data, setData] = useState(['Item 1', 'Item 2']);

  const addItem = (item) => {
    data.push(item); // Mutating the state directly (wrong)
    setData(data); // Will not trigger re-render because the reference is the same
  };

  addItem('Item 3'); // This will not update the UI as expected
};

To achieve immutable state, you should create a new state object:

JSX
import { useState } from 'react';

// Correct immutable state update
const immutableStateExample = () => {
  const [data, setData] = useState(['Item 1', 'Item 2']);

  const addItem = (item) => {
    setData((prevData) => [...prevData, item]); // Creating a new array with the updated data
  };

  addItem('Item 3'); // This will update the UI correctly
};

4. What is the significance of the shouldComponentUpdate lifecycle method in React?

The shouldComponentUpdate method is a lifecycle hook in React that allows you to control whether a component should re-render or not. By default, React will re-render a component whenever its state or props change. However, in some cases, re-rendering may not be necessary, and that’s where shouldComponentUpdate becomes significant.

Example:

JSX
class MyComponent extends React.Component {
  state = {
    count: 0,
  };

  shouldComponentUpdate(nextProps, nextState) {
    // Check if the count has changed
    if (this.state.count !== nextState.count) {
      return true; // Allow re-rendering
    }

    return false; // Prevent re-rendering
  }

  incrementCount = () => {
    this.setState((prevState) => ({ count: prevState.count + 1 }));
  };

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.incrementCount}>Increment</button>
      </div>
    );
  }
}

In this example, the shouldComponentUpdate method checks if the count state has changed. If it hasn’t, the component will not re-render when the button is clicked, saving unnecessary rendering cycles and improving performance.

5. How does React handle or prevent XSS attacks?

React protects against XSS (Cross-Site Scripting) attacks by automatically escaping the values rendered into the DOM. This means that any user-generated content will be sanitized and treated as plain text, preventing malicious code execution.

Example:

JSX
import React from 'react';

const userInput = '<script>alert("XSS Attack!");</script>';

const App = () => {
  return (
    <div>
      {/* React automatically escapes the userInput */}
      <p>{userInput}</p>
    </div>
  );
};

export default App;

In the example above, even though userInput contains potential script tags, React will render it as plain text, displaying it as-is without executing any script.

6. How would you handle side effects on component unmount?

To handle side effects when a component is unmounted (i.e., it is being removed from the DOM), you can use the useEffect hook and return a cleanup function. The cleanup function will be executed when the component is unmounted, allowing you to perform necessary cleanup tasks like clearing timers, unsubscribing from event listeners, etc.

Example:

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

const SideEffectExample = () => {
  const [data, setData] = useState('');

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

    fetchData();

    // Cleanup function to be executed on unmount
    return () => {
      // Perform cleanup tasks here (e.g., clear timers, remove event listeners, etc.)
      console.log('Component unmounted. Cleaning up...');
    };
  }, []);

  return <div>{data}</div>;
};

In this example, the useEffect hook fetches data from an API and sets it in the component’s state. The cleanup function returned from useEffect will be executed when the component is unmounted, logging a message to the console as an example of cleanup.

7. What are React Portals, and where can they be used?

React Portals allow you to render components outside their parent component’s DOM hierarchy. This can be useful for scenarios like creating modal dialogs, tooltips, or dropdown menus that need to be rendered at the top-level of the DOM, separate from the parent component.

Example:

JSX
import ReactDOM from 'react-dom';

const Modal = ({ isOpen, onClose, children }) => {
  if (!isOpen) return null;

  return ReactDOM.createPortal(
    <div className="modal-overlay">
      <div className="modal">
        {children}
        <button onClick={onClose}>Close</button>
      </div>
    </div>,
    document.getElementById('modal-root') // The container element outside the main app
  );
};

const App = () => {
  const [isModalOpen, setIsModalOpen] = useState(false);

  const openModal = () => setIsModalOpen(true);
  const closeModal = () => setIsModalOpen(false);

  return (
    <div>
      <button onClick={openModal}>Open Modal</button>
      <Modal isOpen={isModalOpen} onClose={closeModal}>
        <h2>Modal Content</h2>
        <p>Modal body text goes here...</p>
      </Modal>
    </div>
  );
};

export default App;

In this example, the Modal component is rendered using ReactDOM.createPortal inside the container element with the id modal-root. It allows the modal to be rendered outside the main app component’s DOM hierarchy while still being part of the React component tree.

8. What are Suspense and lazy functions in React?

Suspense is a React feature that allows components to wait for something, such as lazy-loaded components or data fetching, before rendering. It is commonly used with React’s code-splitting capabilities to load components asynchronously, improving application performance.

lazy is a function provided by React that enables lazy loading of components. It returns a promise for the module containing the component and allows you to load it only when it’s needed, rather than upfront.

Example:

JSX
import React, { Suspense } from 'react';

// Lazy loading a component
const LazyComponent = React.lazy(() => import('./LazyComponent'));

const App = () => {
  return (
    <div>
      {/* Suspense with fallback while LazyComponent is loading */}
      <Suspense fallback={<div>Loading...</div>}>
        <LazyComponent />
      </Suspense>
    </div>
  );
};

export default App;

In this example, LazyComponent is loaded asynchronously only when it’s needed. The Suspense component acts as a boundary and shows a fallback content (e.g., “Loading…”) while the component is being loaded. Once the component is ready, it will be rendered in place of the fallback content.

9. How does Error Boundary handle errors in the whole application or part of the application?

Error Boundaries in React are components that catch JavaScript errors during rendering, in lifecycle methods, and in the constructors of the whole component tree below them. They help prevent entire parts of the UI from crashing due to errors in specific components. When an error occurs, the Error Boundary component can gracefully display a fallback UI.

Example:

JSX
class ErrorBoundary extends React.Component {
  state = {
    hasError: false,
    error: null,
    errorInfo: null,
  };

  componentDidCatch(error, errorInfo) {
    this.setState({ hasError: true, error, errorInfo });
  }

  render() {
    if (this.state.hasError) {
      // Render fallback UI
      return (
        <div>
          <h2>Something went wrong.</h2>
          <details style={{ whiteSpace: 'pre-wrap' }}>
            {this.state.error && this.state.error.toString()}
            <br />
            {this.state.errorInfo.componentStack}
          </details>
        </div>
      );
    }

    return this.props.children;
  }
}

const MyComponent = () => {
  if (Math.random() < 0.5) {
    throw new Error('Error occurred in MyComponent.');
  }

  return <div>This is MyComponent.</div>;
};

const App = () => {
  return (
    <ErrorBoundary>
      <MyComponent />
    </ErrorBoundary>
  );
};

export default App;

In this example, the ErrorBoundary component is used to wrap the MyComponent. If an error occurs in MyComponent, the ErrorBoundary catches it and renders the fallback UI. As a result, the entire application doesn’t crash, and the error is gracefully handled.

10. How do you handle an API request error in React?

Handling API request errors in React typically involves using a combination of try and catch blocks when making the API call with fetch or using a library like Axios that provides error handling mechanisms.

Example using fetch:

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

const App = () => {
  const [data, setData] = useState(null);
  const [error, setError] = useState(null);

  const fetchData = async () => {
    try {
      const response = await fetch('https://api.example.com/data');
      if (!response.ok) {
        throw new Error('Network response was not ok.');
      }
      const data = await response.json();
      setData(data);
    } catch (error) {
      setError(error.message);
    }
  };

  return (
    <div>
      {data ? (
        <div>Data loaded successfully: {JSON.stringify(data)}</div>
      ) : error ? (
        <div>Error occurred: {error}</div>
      ) : (
        <

button onClick={fetchData}>Fetch Data</button>
      )}
    </div>
  );
};

export default App;

In this example, the fetchData function uses try and catch to handle any errors that might occur during the API call. If an error occurs, it is caught and stored in the error state, which will be displayed in the UI. If the API call is successful, the data is set in the data state, and it will be displayed in the UI as well.

11. Explain how to use React.forwardRef.

React.forwardRef is a feature in React that allows you to pass a ref from a parent component to a child component that needs access to a DOM element or a React component instance. This is useful when you want to interact with child components directly from a parent component.

Example:

JSX
import React, { useRef } from 'react';

const ChildComponent = React.forwardRef((props, ref) => {
  return <input ref={ref} />;
});

const ParentComponent = () => {
  const inputRef = useRef(null);

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

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

export default ParentComponent;

In this example, the ChildComponent is wrapped with React.forwardRef, allowing the parent component (ParentComponent) to pass a ref (inputRef) directly to the input element inside ChildComponent. The focusInput function in ParentComponent uses the forwarded ref to programmatically focus on the input element when the “Focus Input” button is clicked.

12. What is Concurrent Mode in React?

Concurrent Mode is an experimental feature in React that aims to improve the responsiveness and performance of the UI. It allows React to work on rendering components and handling updates concurrently, breaking the rendering work into smaller units to provide a more fluid user experience.

Example:

JSX
import { unstable_concurrentAct as act } from 'react-dom/test-utils'; // Only for testing Concurrent Mode

const App = () => {
  const [data, setData] = useState(null);

  // Simulating an asynchronous operation
  useEffect(() => {
    // Start fetching data
    act(() => {
      setTimeout(() => {
        setData('Data loaded successfully.');
      }, 2000);
    });
  }, []);

  return <div>{data ? data : 'Loading...'}</div>;
};

export default App;

In this example, we’re using unstable_concurrentAct from react-dom/test-utils to simulate Concurrent Mode (Note: this API is intended for testing only and may change in the future). The App component sets a timeout to simulate an asynchronous operation, and during this time, the component can still respond to user interactions and update the UI.

13. What are the rules for Hooks usage in React?

The rules for using Hooks in React are as follows:

  1. Hooks should only be used at the top level of the functional component or inside other custom hooks. They should not be used inside loops, conditions, or nested functions.
  2. Hooks should always be called in the same order. This rule ensures that React can keep track of the state and props correctly.
  3. Custom hooks should always start with the prefix “use” (e.g., useCustomHook). This convention helps identify custom hooks easily.
  4. Hooks should not be called in regular JavaScript functions. They are meant to be used in functional components or other custom hooks.
  5. Only call Hooks from React functional components or other custom Hooks. Avoid calling them in regular JavaScript functions, class components, or event handlers.

14. What are custom hooks? Provide an example.

Custom hooks are functions in React that allow you to reuse stateful logic between different components. They follow the “use” prefix convention and can encapsulate complex logic, making it easier to share code among components.

Example:

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

// Custom hook to fetch data
const useFetchData = (url) => {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(url);
        const data = await response.json();
        setData(data);
      } catch (error) {
        console.error('Error fetching data:', error);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, [url]);

  return { data, loading };
};

// Using the custom hook in a component
const MyComponent = () => {
  const { data, loading } = useFetchData('https://api.example.com/data');

  if (loading) {
    return <div>Loading...</div>;
  }

  return <div>{data ? JSON.stringify(data) : 'No data available.'}</div>;
};

export default MyComponent;

In this example, the useFetchData custom hook encapsulates the data-fetching logic. The MyComponent uses this custom hook to fetch data from the given URL and handle loading states. By using the custom hook, the data-fetching logic can be reused across multiple components, promoting code reusability and readability.

15. Explain how to use the useReducer hook.

The useReducer hook is an alternative to useState for managing complex state logic in React. It takes a reducer function and an initial state, returns the current state and a dispatch function to update the state.

Example:

JSX
import { useReducer } from 'react';

// Reducer function
const reducer = (state, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return { count: state.count + 1 };
    case 'DECREMENT':
      return { count: state.count - 1 };
    default:
      return state;
  }
};

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

  return (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'INCREMENT' })}>Increment</button>
      <button onClick={() => dispatch({ type: 'DECREMENT' })}>Decrement</button>
    </div>
  );
};

export default Counter;

In this example, the useReducer hook manages the state of the count. The reducer function specifies how the state should be updated based on different actions (e.g., INCREMENT, DECREMENT). The dispatch function is used to trigger the corresponding actions, and the state is updated accordingly.

16. What is the purpose of the useCallback hook?

The useCallback hook is used to memoize functions to prevent unnecessary re-creations of function instances, especially when passed down to child components. It is particularly useful when dealing with performance optimizations and preventing excessive re-rendering of child components.

Example:

JSX
import { useState, useCallback } from 'react';

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

  const increment = useCallback(() => {
    setCount((prevCount) => prevCount + 1);
  }, []); // Empty dependency array ensures the same instance is used for the callback

  return (
    <div>
      <p>Count: {count}</p>
      <ChildComponent increment={increment} />
    </div>
  );
};

const ChildComponent = ({ increment }) => {
  return (
    <div>
      <button onClick={increment}>Increment</button>
    </div>
  );
};

export default ParentComponent;

In this example, the increment function is wrapped in useCallback. This ensures that the same instance of the increment function is used across renders of ParentComponent, preventing unnecessary re-creation of the function and potential re-renders of ChildComponent.

17. What is the purpose of the useMemo hook?

The useMemo hook is used to memoize the result of a computation, allowing you to avoid unnecessary re-computation of expensive functions when the dependencies haven’t changed. It is useful for optimizing performance by preventing redundant calculations.

Example:

JSX
import { useState, useMemo } from 'react';

const ExpensiveComputationComponent = () => {
  const [count, setCount] = useState(1);

  const expensiveResult = useMemo(() => {
    console.log('Expensive computation is performed.'); // This log will only appear when the count changes
    return count * 1000; // Some expensive computation based on count
  }, [count]); // Dependency array ensures re-computation only when count changes

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

export default ExpensiveComputationComponent;

In this example, the expensiveResult is calculated using useMemo. The function inside useMemo will be executed only when the value of count changes, ensuring that the expensive computation is performed only when necessary.

18. Explain how you would implement a dark mode in React.

Implementing dark mode in React can be achieved using state management, CSS variables, or third-party libraries like styled-components. Below is an example using CSS variables:

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

const DarkModeComponent = () => {
  const [darkMode, setDarkMode] = useState(false);

  // Check local storage for saved dark mode preference on initial load
  useEffect(() => {
    const savedDarkMode = localStorage.getItem('darkMode');
    if (savedDarkMode) {
      setDarkMode(savedDarkMode === 'true');
    }
  }, []);

  // Save dark mode preference to local storage whenever it changes
  useEffect(() => {
    localStorage.setItem('darkMode', darkMode.toString());
  }, [darkMode]);

  return (
    <div className={darkMode ? 'dark-mode' : 'light-mode'}>
      <h1>Dark Mode Example</h1>
      <button onClick={() => setDarkMode((prevDarkMode) => !prevDarkMode)}>
        Toggle Dark Mode
      </button>
    </div>
  );
};

export default DarkModeComponent;

In this example, we store the dark mode preference in local storage to persist the user’s preference across page reloads. When the user toggles dark mode, the darkMode state is updated, and the class name is changed dynamically to apply the dark or light mode styles using CSS variables.

19. How do you optimize large lists in React?

Optimizing large lists in React can be achieved using the react-window library or the react-virtualized library. These libraries use windowing techniques to render only the visible items, which significantly improves performance when dealing with long lists.

Here’s an example using react-window:

JSX
npm install react-window
JSX
import React from 'react';
import { FixedSizeList as List } from 'react-window';

const LargeList = () => {
  // Sample data with 1000 items
  const data = Array.from(Array(1000).keys());

  // Render an individual item
  const renderItem = ({ index, style }) => {
    return <div style={style}>{data[index]}</div>;
  };

  return (
    <List
      height={500} // Height of the visible window
      width={300} // Width of the visible window
      itemCount={data.length} // Total number of items
      itemSize={30} // Height of each item
    >
      {renderItem}
    </List>
  );
};

export default LargeList;

In this example, react-window is used to render the list efficiently by rendering only the visible items, no matter how large the list is. The FixedSizeList component takes care of the windowing technique, and you provide it with the height, width, itemCount, and itemSize to determine the list’s dimensions and item heights.

20. What are your strategies for managing complex state interactions?

When managing complex state interactions in React, you can follow these strategies:

  1. State Normalization: Normalize your state to keep it flat and avoid redundancy. Use data structures like objects and arrays to organize data efficiently.
  2. Stateful Components: Use stateful components (class components or useState hook) to manage local component-specific state.
  3. State Lifting: If state needs to be shared between components, lift the state to the closest common ancestor of those components and pass it down as props.
  4. UseReducer: For complex state logic, use useReducer to encapsulate state updates and actions in a single reducer function.
  5. Custom Hooks: Create custom hooks to encapsulate reusable state logic and share it across different components.
  6. Context API: Use the Context API to provide state globally to components that need it without passing props manually.
  7. Immutability: Always update state immutably to avoid side effects and ensure proper re-renders.

21. How do you handle actions that have side effects?

For actions that have side effects, such as data fetching or interacting with external APIs, you can use middleware in Redux or useEffect in React.

Example using useEffect:

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

const DataFetchingComponent = () => {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch('https://api.example.com/data');
        const data = await response.json();
        setData(data);
      } catch (error) {
        console.error('Error fetching data:', error);
      } finally

 {
        setLoading(false);
      }
    };

    fetchData();
  }, []);

  return (
    <div>
      {loading ? <div>Loading...</div> : <div>{JSON.stringify(data)}</div>}
    </div>
  );
};

export default DataFetchingComponent;

In this example, the useEffect hook is used to fetch data from an API when the component mounts. The side effect of fetching data is handled within the useEffect function. The component displays “Loading…” while the data is being fetched and then renders the fetched data once it’s available.

22. What are the downsides of using ReactJS?

While ReactJS is a popular and powerful framework, it does have some downsides:

  1. Learning Curve: ReactJS has a steep learning curve for beginners, especially when dealing with advanced concepts like Redux and React Router.
  2. Fragmentation: The ecosystem of ReactJS has a vast number of libraries and tools, which can lead to fragmentation and make it challenging to choose the right tools for your project.
  3. Boilerplate Code: ReactJS can lead to a lot of boilerplate code, especially when managing state and props manually in class components.
  4. Performance Concerns: ReactJS’s Virtual DOM can sometimes lead to performance issues when handling large and complex component trees.
  5. Overhead: ReactJS might be overkill for small projects, adding unnecessary complexity.

Example of boilerplate code in class components:

JSX
import React, { Component } from 'react';

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

  incrementCount = () => {
    this.setState((prevState) => ({ count: prevState.count + 1 }));
  };

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.incrementCount}>Increment</button>
      </div>
    );
  }
}

export default Counter;

In this example, the class component introduces more boilerplate code, like the constructor and manually binding methods. This can be avoided using functional components and hooks.

23. Explain the difference between the useState and useReducer hooks. When would you use one over the other?

useState and useReducer are both hooks used to manage state in React, but they have some differences:

  1. useState: useState is a simpler hook that is commonly used for managing simple state updates. It returns a state variable and a function to update that state.

Example:

JSX
import { useState } from 'react';

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

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

export default Counter;
  1. useReducer: useReducer is more powerful and flexible for managing complex state logic. It takes a reducer function and an initial state, and it returns the current state and a dispatch function to update the state. It is commonly used for state that involves multiple actions and transitions.

Example:

JSX
import { useReducer } from 'react';

const initialState = { count: 0 };

const reducer = (state, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return { count: state.count + 1 };
    case 'DECREMENT':
      return { count: state.count - 1 };
    default:
      return state;
  }
};

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

  return (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'INCREMENT' })}>Increment</button>
      <button onClick={() => dispatch({ type: 'DECREMENT' })}>Decrement</button>
    </div>
  );
};

export default Counter;

When to use useState over useReducer:

  • For simple state updates that involve a single value.
  • For components with less complex state management.

When to use useReducer over useState:

  • For complex state logic with multiple actions and transitions.
  • When you need to pass down dispatch functions to deeply nested components.

24. What is server-side rendering, and what are its benefits?

Server-Side Rendering (SSR) is a technique where the initial render of a web application is performed on the server, and the resulting HTML is sent to the client. It enables search engines to crawl the content and improves the initial loading time for users.

Example using Next.js (a popular framework for SSR in React):

JSX
npx create-next-app my-app
cd my-app
npm run dev

In this example, Next.js automatically enables SSR by default. When you run the application and check the page source, you will see the rendered HTML on the server.

Benefits of Server-Side Rendering:

  • Improved SEO: Search engines can index the content as it’s rendered on the server, leading to better SEO rankings.
  • Faster Initial Load: Users see the content more quickly since the server sends the initial HTML, reducing the time to first meaningful paint.
  • Accessibility: Users with slow internet connections or non-JavaScript browsers can still view the content.

25. What is React.lazy, and when would you use it?

React.lazy is a function that allows you to lazy-load components and their dependencies, making it possible to split your code into smaller chunks and load them on-demand, improving the performance of your application.

Example:

JSX
import React, { lazy, Suspense } from 'react';

const LazyComponent = lazy(() => import('./LazyComponent'));

const App = () => {
  return (
    <div>
      {/* Suspense with fallback while LazyComponent is loading */}
      <Suspense fallback={<div>Loading...</div>}>


        <LazyComponent />
      </Suspense>
    </div>
  );
};

export default App;

In this example, LazyComponent is lazy-loaded using React.lazy. When App is rendered, LazyComponent is loaded only when it’s needed (e.g., when the component is mounted). While LazyComponent is loading, the Suspense component displays a fallback UI (e.g., “Loading…”) until the actual component is ready to be rendered.

26. How would you handle multiple API calls?

Handling multiple API calls can be done using Promise.all, which allows you to make several asynchronous requests concurrently and wait for all of them to resolve.

Example:

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

const App = () => {
  const [data1, setData1] = useState(null);
  const [data2, setData2] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const [response1, response2] = await Promise.all([
          fetch('https://api.example.com/data1'),
          fetch('https://api.example.com/data2'),
        ]);
        const data1 = await response1.json();
        const data2 = await response2.json();
        setData1(data1);
        setData2(data2);
      } catch (error) {
        console.error('Error fetching data:', error);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, []);

  if (loading) {
    return <div>Loading...</div>;
  }

  return (
    <div>
      <p>Data 1: {data1 ? JSON.stringify(data1) : 'No data available.'}</p>
      <p>Data 2: {data2 ? JSON.stringify(data2) : 'No data available.'}</p>
    </div>
  );
};

export default App;

In this example, two API calls are made simultaneously using Promise.all. The component waits for both requests to resolve, and once they are both ready, it sets the data in the state and renders the results.

27. How do you test React components?

Testing React components can be done using testing libraries like @testing-library/react or Enzyme. The following is an example using @testing-library/react:

Example using @testing-library/react and jest:

JSX
npm install @testing-library/react @testing-library/jest-dom --save-dev
JSX
// Counter.js
import React, { useState } from 'react';

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

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

export default Counter;
JSX
// Counter.test.js
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import Counter from './Counter';

test('counter increments when the button is clicked', () => {
  render(<Counter />);
  const countElement = screen.getByText('Count: 0');
  const buttonElement = screen.getByText('Increment');

  expect(countElement).toBeInTheDocument();
  expect(countElement).toHaveTextContent('Count: 0');

  fireEvent.click(buttonElement);

  expect(countElement).toHaveTextContent('Count: 1');
});

In this example, we test the Counter component using @testing-library/react. We render the component, interact with the button using fireEvent.click, and then assert that the count has incremented correctly using expect and toHaveTextContent.

28. What is Snapshot testing in React?

Snapshot testing is a form of testing in React that allows you to capture a rendered component’s output and compare it against a previously saved “snapshot” of the component’s output. It’s a quick way to detect unexpected changes in the UI.

Example using @testing-library/react and jest:

JSX
npm install @testing-library/react @testing-library/jest-dom --save-dev
JSX
// Counter.js
import React, { useState } from 'react';

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

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

export default Counter;
JSX
// Counter.test.js
import React from 'react';
import { render } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import Counter from './Counter';

test('snapshot testing for Counter component', () => {
  const { asFragment } = render(<Counter />);
  expect(asFragment()).toMatchSnapshot();
});

In this example, we use asFragment from @testing-library/react to capture the rendered output of the Counter component and compare it with a previously saved snapshot. If there are any unexpected changes, the test will fail, and you can review and update the snapshot accordingly.

29. What is the difference between Real DOM and Virtual DOM?

Real DOMVirtual DOM
Represents the actual HTML structure of a web pageRepresents a lightweight copy of the Real DOM in memory
Any changes to the DOM result in reflow and repaint, which can be slowChanges to the Virtual DOM are made in memory and don’t cause reflow and repaint
Updating the Real DOM directly is relatively slower and less efficientUpdating the Virtual DOM is faster and more efficient
Manipulating the Real DOM can lead to performance issues, especially in large and complex applicationsVirtual DOM reduces the risk of performance issues by batching and optimizing updates
Accessing the Real DOM elements is more expensive in terms of time and memoryVirtual DOM allows for more efficient access to elements for comparison and update
Real DOM updates can cause screen flickering and a poor user experienceVirtual DOM updates minimize flickering and improve user experience

30. What is the context in React, and how and when would you use it?

React Context is a feature that allows you to pass data through the component tree without having to pass props explicitly at every level. It provides a way to share state or data between components that are not directly related.

You can use React Context when you have data that needs to be accessed by multiple components, like themes, user authentication, or language preferences. It helps avoid prop drilling, where props are passed through multiple levels of components just to reach the component that needs the data.

You create a context using React.createContext() and provide a value to the context using a Provider. Any component wrapped in the Provider can access the value using the useContext hook or Consumer.

Example:

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

// Create a context
const ThemeContext = React.createContext('light');

// Provide the value using a Provider
const App = () => {
  return (
    <ThemeContext.Provider value="dark">
      <ChildComponent />
    </ThemeContext.Provider>
  );
};

// Use the context value in ChildComponent using useContext hook
const ChildComponent = () => {
  const theme = useContext(ThemeContext);

  return (
    <div>
      <p>Theme: {theme}</p>
    </div>
  );
};

In this example, the ThemeContext is created with the default value 'light'. The App component wraps ChildComponent in the ThemeContext.Provider, providing the value 'dark'. ChildComponent uses the useContext hook to access the theme value provided by the ThemeContext.Provider.

31. What is Redux Saga?

Redux Saga is a middleware library for Redux that allows you to handle side effects like data fetching and asynchronous actions in a more structured and testable way. It uses ES6 Generators to write asynchronous code that is easier to read and maintain.

Example:

JSX
npm install redux redux-saga
JSX
// actions.js
export const fetchUserRequest = () => ({
  type: 'FETCH_USER_REQUEST',
});

export const fetchUserSuccess = (user) => ({
  type: 'FETCH_USER_SUCCESS',
  payload: user,
});

export const fetchUserFailure = (error) => ({
  type: 'FETCH_USER_FAILURE',
  payload: error,
});
JSX
// reducer.js
const initialState = {
  user: {},
  loading: false,
  error: null,
};

const userReducer = (state = initialState, action) => {
  switch (action.type) {
    case 'FETCH_USER_REQUEST':
      return { ...state, loading: true, error: null };
    case 'FETCH_USER_SUCCESS':
      return { ...state, user: action.payload, loading: false, error: null };
    case 'FETCH_USER_FAILURE':
      return { ...state, loading: false, error: action.payload };
    default:
      return state;
  }
};

export default userReducer;
JSX
// saga.js
import { takeEvery, call, put } from 'redux-saga/effects';
import { fetchUserSuccess, fetchUserFailure } from './actions';

function* fetchUser() {
  try {
    // Simulating an API call
    const response = yield call(fetch, 'https://api.example.com/user');
    const user = yield call([response, 'json']);
    yield put(fetchUserSuccess(user));
  } catch (error) {
    yield put(fetchUserFailure(error.message));
  }
}

function* userSaga() {
  yield takeEvery('FETCH_USER_REQUEST', fetchUser);
}

export default userSaga;
JSX
// store.js
import { createStore, applyMiddleware } from 'redux';
import createSagaMiddleware from 'redux-saga';
import userReducer from './reducer';
import userSaga from './saga';

const sagaMiddleware = createSagaMiddleware();
const store = createStore(userReducer, applyMiddleware(sagaMiddleware));

sagaMiddleware.run(userSaga);

export default store;

In this example, we have a simple Redux setup with actions, reducer, and a Saga. The Saga listens for 'FETCH_USER_REQUEST' actions and performs an asynchronous API call. If the call is successful, it dispatches 'FETCH_USER_SUCCESS' with the user data, or if there’s an error, it dispatches 'FETCH_USER_FAILURE' with the error message.

32. Explain the concept of Middleware in Redux.

Middleware in Redux provides a way to intercept dispatched actions before they reach the reducer. It allows you to add additional functionality to Redux, such as logging, asynchronous actions, or other side effects.

Middleware is applied using applyMiddleware from the Redux library. It sits between the dispatch function and the reducer and can modify or handle actions as they flow through.

Each middleware receives the store object and next function as arguments. Middleware can choose to let the action pass to the next middleware using next(action) or prevent it from reaching the reducer altogether.

Example of a simple logger middleware:

JSX
const loggerMiddleware = (store) => (next) => (action) => {
  console.log('Action:', action);
  const result = next(action);
  console.log('New State:', store.getState());
  return result;
};

// Usage in store.js
import { createStore, applyMiddleware } from 'redux';
import userReducer from './reducer';
import loggerMiddleware from './loggerMiddleware';

const store = createStore(userReducer, applyMiddleware(loggerMiddleware));

In this example, the loggerMiddleware logs the action before it reaches the reducer and the new state after the reducer updates the state. You can add multiple middleware functions by passing them as arguments to applyMiddleware.

33. What are the common performance issues in React, and how would you optimize them?

Common performance issues in React and their optimizations include:

  1. Unnecessary Re-renders: Optimize rendering by using React.memo or shouldComponentUpdate to prevent re-renders of components when their props or state haven’t changed.
  2. Excessive State Updates: Reduce state updates using useReducer or batch state updates with setState or useState functional updates.
  3. Inefficient List Rendering: Use windowing libraries like react-window or react-virtualized for rendering large lists efficiently.
  4. Large Component Trees: Split components into smaller, more manageable pieces using composition or React’s Context API.
  5. Inefficient DOM Manipulation: Use CSS classes for styling changes instead of direct DOM manipulation. Consider using libraries like styled-components for better performance.
  6. Deep Nesting of Components: Avoid excessive nesting, as it can lead to reduced performance. Flatten component hierarchies where possible.
  7. Excessive Event Listeners: Remove or optimize event listeners to avoid unnecessary computations on each event trigger.
  8. Unoptimized Images: Compress and resize images to reduce their size and improve page load time.

34. How do you ensure component methods have the correct ‘this’ context in React?

In class components, to ensure that component methods have the correct this context, you can bind the method in the constructor or use class properties syntax.

  1. Binding in the Constructor:
JSX
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0,
    };
    this.increment = this.increment.bind(this);
  }

  increment() {
    // Now, 'this' refers to the component instance
    this.setState((prevState) => ({ count: prevState.count + 1 }));
  }

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.increment}>Increment</button>
      </div>
    );
  }
}
  1. Class Properties Syntax (with Babel):
JSX
class MyComponent extends React.Component {
  state = {
    count: 0,
  };

  increment = () => {
    // Now, 'this' refers to the component instance
    this.setState((prevState) => ({ count: prevState.count + 1 }));
  };

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.increment}>Increment</button>
      </div>
    );
  }
}

In functional components, the this context is not an issue because there are no instances involved. However, if you need to use a value or a function that depends on the component’s instance, you can use the useRef hook to hold the reference to the component instance.

Example:

JSX
import React, { useRef } from 'react';

const MyComponent = () => {
  const countRef = useRef(0);

  const increment = () => {
    countRef.current += 1;
    console.log('Count:', countRef.current);
  };

  return (
    <div>
      <button onClick={increment}>Increment</button>
    </div>
  );
};

export default MyComponent;

In this example, we use useRef to create a mutable reference countRef, which holds the value of count. The increment function accesses and updates countRef.current to maintain the state across renders.

35. What are the different ways to style a React component?

There are several ways to style a React component:

  1. Inline Styling: You can apply styles directly to a component using the style prop, which accepts an object with CSS properties.
JSX
const InlineStyledComponent = () => {
  const styles = {
    color: 'red',
    fontSize: '18px',
    fontWeight: 'bold',
  };

  return <div style={styles}>Inline Styled Component</div>;
};
  1. CSS Stylesheets: You can use traditional CSS stylesheets and import them into your component.
JSX
/* styles.css */
.container {
  color: blue;
  font-size: 20px;
}
JSX
import React from 'react';
import './styles.css';

const CSSStyledComponent = () => {
  return <div className="container">CSS Styled Component</div>;
};
  1. CSS Modules: CSS Modules allow you to create local CSS classes specific to a component and avoid class name collisions.
JSX
/* styles.module.css */
.container {
  color: green;
  font-size: 24px;
}
JSX
import React from 'react';
import styles from './styles.module.css';

const CSSModuleStyledComponent = () => {
  return <div className={styles.container}>CSS Module Styled Component</div>;
};
  1. CSS-in-JS Libraries: There are libraries like styled-components and emotion that allow you to write CSS directly in your JavaScript code.

Using styled-components:

JSX
npm install styled-components
JSX
import React from 'react';
import styled from 'styled-components';

const StyledComponent = styled.div`
  color: purple;
  font-size: 22px;
`;

const StyledComponentExample = () => {
  return <StyledComponent>Styled Component Example</StyledComponent>;
};

MCQ Questions

1. What is React?

a) A JavaScript library for building user interfaces.
b) A programming language.
c) An operating system.
d) A database management system.

Answer: a) A JavaScript library for building user interfaces.

2. Who developed React?

a) Microsoft
b) Apple
c) Google
d) Facebook

Answer: d) Facebook

3. What is the virtual DOM in React?

a) A JavaScript framework.
b) A lightweight version of the DOM.
c) A concept used in server-side rendering.
d) A data structure that represents the actual DOM tree.

Answer: d) A data structure that represents the actual DOM tree.

4. What is JSX in React?

a) A programming language.
b) A templating engine.
c) A syntax extension for JavaScript.
d) A query language for databases.

Answer: c) A syntax extension for JavaScript.

5. What is the purpose of render() in React?

a) To define the initial state of a component.
b) To handle user events.
c) To update the UI based on the component’s state.
d) To perform asynchronous operations.

Answer: c) To update the UI based on the component’s state.

6. What are React components?

a) Functions that return HTML.
b) CSS stylesheets.
c) Data structures for storing component state.
d) Mathematical formulas.

Answer: a) Functions that return HTML.

7. What is state in React?

a) A CSS property for styling components.
b) A data structure for storing component-specific data.
c) An event triggered by user interactions.
d) A method for rendering components.

Answer: b) A data structure for storing component-specific data.

8. What is props in React?

a) A method for updating component state.
b) A data structure for passing data between components.
c) A virtual DOM representation of a component.
d) A styling technique for React components.

Answer: b) A data structure for passing data between components.

9. What is the purpose of keys in React lists?

a) To optimize rendering performance.
b) To uniquely identify elements in a list.
c) To define component lifecycle methods.
d) To handle user input in forms.

Answer: b) To uniquely identify elements in a list.

10. What is the significance of React’s componentDidMount() lifecycle method?

a) It is called before rendering a component.
b) It is called after a component has been updated.
c) It is called when a component is about to be removed from the DOM.
d) It is called when a component has been inserted into the DOM.

Answer: d) It is called when a component has been inserted into the DOM.

11. What is the purpose of React Router?

a) To handle asynchronous API requests.
b) To manage state in React components.
c) To navigate between different pages in a single-page application.
d) To optimize rendering performance.

Answer: c) To navigate between different pages in a single-page application.

12. What is Redux in React?

a) A server-side rendering framework.
b) A state management library.
c) A CSS-in-JS solution.
d) A database management system.

Answer: b) A state management library.

13. What is the purpose of React’s PureComponent?

a) To optimize rendering performance.
b) To handle user interactions.
c)To define component lifecycle methods.
d) To encapsulate CSS styles.

Answer: a) To optimize rendering performance.

14. What is the role of the shouldComponentUpdate() lifecycle method in React?

a) It is called before rendering a component.
b) It is called after a component has been updated.
c) It determines whether a component should re-render or not.
d) It handles errors that occur during rendering.

Answer: c) It determines whether a component should re-render or not.

15. What is the purpose of React’s useContext() hook?

a) To handle user authentication.
b) To manage component state.
c) To consume values from a React context.
d) To perform server-side rendering.

Answer: c) To consume values from a React context.

16. What is the significance of React’s useMemo() hook?

a) To optimize rendering performance.
b) To handle user interactions.
c) To define component lifecycle methods.
d) To perform asynchronous operations.

Answer: a) To optimize rendering performance.

17. What is the purpose of React’s useCallback() hook?

a) To handle user events.
b) To define component lifecycle methods.
c) To memoize functions and optimize performance.
d) To perform server-side rendering.

Answer: c) To memoize functions and optimize performance.

18. What is the role of React’s useRef() hook?

a) To manage component state.
b) To handle user events.
c) To create references to DOM elements.
d) To perform server-side rendering.

Answer: c) To create references to DOM elements.

19. What is the purpose of React’s useReducer() hook?

a) To manage component state.
b) To handle user authentication.
c) To optimize rendering performance.
d) To perform asynchronous operations.

Answer: a) To manage component state.

20. What is the concept of React Fragments?

a) A feature for creating reusable components.
b) A syntax for defining inline styles in React components.
c) A way to render multiple elements without using a wrapper element.
d) A technique for server-side rendering in React.

Answer: c) A way to render multiple elements without using a wrapper element.

21. What is the purpose of React’s useEffect() hook?

a) To handle user interactions.
b) To define component lifecycle methods.
c) To perform server-side rendering.
d) To manage side effects in functional components.

Answer: d) To manage side effects in functional components.

22. What is the concept of React Context?

a) A state management solution in React.
b) A mechanism for sharing data between components without passing props.
c) A library for handling form validation in React.
d) A tool for optimizing rendering performance in React applications.

Answer: b) A mechanism for sharing data between components without passing props.

23. What is the role of React’s useState() hook?

a) To handle user authentication.
b) To manage component state in functional components.
c) To define component lifecycle methods.
d) To perform server-side rendering.

Answer: b) To manage component state in functional components.

24. What is the purpose of React’s forwardRef() function?

a) To optimize rendering performance in React applications.
b) To create reusable higher-order components.
c) To pass refs to child components in React.
d) To handle asynchronous operations in React.

Answer: c) To pass refs to child components in React.

25. What is the role of React’s useContext() hook?

a) To handle user authentication.
b) To manage component state.
c) To consume values from a React context.
d) To perform server-side rendering.

Answer: c) To consume values from a React context

26. What is the significance of React’s memo() function?

a) To optimize rendering performance in React applications.
b) To create reusable higher-order components.
c) To handle user interactions.
d) To perform server-side rendering.

Answer: a) To optimize rendering performance in React applications.

27. What is the concept of React Router?

a) A state management library in React.
b) A mechanism for handling user interactions in React.
c) A library for handling routing and navigation in React applications.
d) A tool for optimizing rendering performance in React.

Answer: c) A library for handling routing and navigation in React applications

28. What is the purpose of React’s useReducer() hook?

a) To manage component state.
b) To handle user authentication.
c) To optimize rendering performance.
d) To perform asynchronous operations.

Answer: a) To manage component state.

29. What is the role of React’s useCallback() hook?

a) To handle user events.
b) To define component lifecycle methods.
c) To memoize functions and optimize performance.
d) To perform server-side rendering.

Answer: c) To memoize functions and optimize performance.

30. What is the concept of React Fragments?

a) A feature for creating reusable components.
b) A syntax for defining inline styles in React components.
c) A way to render multiple elements without using a wrapper element.
d) A technique for server-side rendering in React.

c) A way to render multiple elements without using a wrapper element.

Deepak Vishwakarma

Founder

RELATED Articles

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.