React Interview Questions (Part 2): Component Lifecycle & Hooks

Yusuf UysalYusuf Uysal
4 min read

What are the differences between componentDidMount, componentDidUpdate, and componentWillUnmount in class components?

componentDidMount, componentDidUpdate, and componentWillUnmount are lifecycle methods in React class components that are invoked at different stages of a component's lifecycle:

  • componentDidMount: This method is called once, immediately after the component is mounted to the DOM (right after the initial render). It's commonly used to initialize data (e.g., making API calls) or set up subscriptions (e.g., event listeners).

  • componentDidUpdate: This method is called after every update (re-render) of the component, except for the initial render. It can be used to perform actions based on changes to props or state, such as fetching new data or updating the DOM.

  • componentWillUnmount: This method is invoked right before a component is removed (unmounted) from the DOM. Itโ€™s typically used to clean up resources, such as cancelling API requests or removing event listeners.

How does React manage the component lifecycle in function components using hooks?

In function components, React manages the lifecycle through hooks, primarily useState, useReducer, and useEffect:

  • State Updates (useState and useReducer): When the state is updated using useState or useReducer, React triggers a re-render of the component. During this re-render, a new virtual DOM is created, which is compared to the previous virtual DOM (using a process called "reconciliation"). React then makes the necessary updates to the actual DOM, minimizing changes to only what is required, improving performance.

  • Effects (useEffect): The useEffect hook is used to handle side effects in function components. You can control when the effect runs by specifying dependencies in the dependency array. Whenever the dependencies change, React re-runs the effect. This is useful for actions like data fetching, DOM manipulation, or subscribing/unsubscribing from services. By managing side effects this way, React ensures that the UI stays in sync with state and prop changes.

What is the useRef hook used for?

The useRef hook in React is primarily used for two purposes:

  1. Accessing and Manipulating DOM Elements: useRef allows you to access a DOM element and persist a reference to it across renders without triggering a re-render. It's useful for tasks like focusing an input, controlling media, or manipulating elements. Unlike useState, changing a useRef value doesn't cause a re-render.

Example:

function InputFocus() {
  const inputRef = useRef();

  useEffect(() => {
    inputRef.current.focus(); // Focuses the input after the component mounts
  }, []);

  return <input ref={inputRef} />;
}
  1. Storing Mutable Values Across Renders: useRef can also be used to store any mutable value that persists across renders but doesn't trigger a re-render when updated. This is useful for keeping track of things like timers, previous values, or any value that doesnโ€™t need to cause a re-render when it changes.

Example:

function Timer() {
  const timerId = useRef();

  const startTimer = () => {
    timerId.current = setInterval(() => {
      console.log('Timer running...');
    }, 1000);
  };

  const stopTimer = () => {
    clearInterval(timerId.current);
  };

  return (
    <div>
      <button onClick={startTimer}>Start</button>
      <button onClick={stopTimer}>Stop</button>
    </div>
  );
}

What are custom hooks, and how do you create one?

In React, custom hooks allow you to extract and reuse logic between components, helping to keep your code more modular and maintainable. Custom hooks are simply JavaScript functions that can call other hooks like useState, useEffect, or any other React hooks, and they follow the convention of naming with a use prefix.

Creating a Custom Hook: A custom hook is created by defining a function that bundles logic (like state management or side effects) and can be shared across components. For example, if you want to reuse a data-fetching logic in multiple components, you can encapsulate it into a custom hook.

function useFetchData(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    async function fetchData() {
      const response = await fetch(url);
      const result = await response.json();
      setData(result);
      setLoading(false);
    }
    fetchData();
  }, [url]);

  return { data, loading };
}

In this example, the useFetchData custom hook fetches data from a URL and can be reused across different components. You call this custom hook just like you would call a built-in hook:

function MyComponent() {
  const { data, loading } = useFetchData('https://api.example.com/data');

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

What is React.memo, and when should you use it?

React.memo is a higher-order component used for performance optimization. It prevents unnecessary re-renders by memoizing a component's output. When you wrap a component with React.memo, React will only re-render the component if its props change. If the props remain the same, the component will skip re-rendering, thus improving performance in situations where re-renders are costly.

Example:

const MyComponent = React.memo(function MyComponent({ name }) {
  return <div>{name}</div>;
});

In this example, MyComponent will only re-render if the name prop changes.

0
Subscribe to my newsletter

Read articles from Yusuf Uysal directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Yusuf Uysal
Yusuf Uysal

๐——๐—ฟ๐—ถ๐˜ƒ๐—ฒ๐—ป ๐—™๐—ฟ๐—ผ๐—ป๐˜๐—ฒ๐—ป๐—ฑ ๐——๐—ฒ๐˜ƒ๐—ฒ๐—น๐—ผ๐—ฝ๐—ฒ๐—ฟ with extensive experience in JavaScript, React.js, and Next.js. I help companies enhance user engagement and deliver high-performance web applications that are responsive, accessible, and visually appealing. Beyond my technical skills, I am a ๐—ฐ๐—ผ๐—น๐—น๐—ฎ๐—ฏ๐—ผ๐—ฟ๐—ฎ๐˜๐—ถ๐˜ƒ๐—ฒ ๐˜๐—ฒ๐—ฎ๐—บ ๐—ฝ๐—น๐—ฎ๐˜†๐—ฒ๐—ฟ who thrives in environments that value continuous learning and innovation. I enjoy projects where I can leverage my expertise in ๐—ฟ๐—ฒ๐˜€๐—ฝ๐—ผ๐—ป๐˜€๐—ถ๐˜ƒ๐—ฒ ๐—ฑ๐—ฒ๐˜€๐—ถ๐—ด๐—ป, ๐—ฏ๐—ฟ๐—ผ๐˜„๐˜€๐—ฒ๐—ฟ ๐—ฐ๐—ผ๐—บ๐—ฝ๐—ฎ๐˜๐—ถ๐—ฏ๐—ถ๐—น๐—ถ๐˜๐˜†, ๐—ฎ๐—ป๐—ฑ ๐˜„๐—ฒ๐—ฏ ๐—ฝ๐—ฒ๐—ฟ๐—ณ๐—ผ๐—ฟ๐—บ๐—ฎ๐—ป๐—ฐ๐—ฒ to deliver seamless user experiences. I get excited about opportunities where I can contribute to creating dynamic, user-focused applications while working closely with cross-functional teams to drive impactful results. I love connecting with new people, and you can reach me at yusufuysal.dev@gmail.com.