Home   reactjs  

How useState and useEffect work internally in React

Understanding how useState and useEffect work internally in React provides insights into their behavior and optimizations within functional components.

useState Internals

  1. Initialization:

    • When a functional component is rendered for the first time, React initializes the state using the initial value provided to useState.
    • It stores the current state value (value) and a function (setValue) to update that state.
  2. State Management:

    • React uses closures to maintain the current state between re-renders without losing its value.
    • Each call to useState returns the current state value and a function to update it (setValue).
  3. Updating State:

    • When setValue(newValue) is called, React schedules a re-render of the component with the updated state value.
    • It uses a queue mechanism to batch state updates for performance optimization.
  4. Re-rendering:

    • React compares the new state value (newValue) with the previous one (value) using a shallow comparison (Object.is).
    • If they differ, React schedules a re-render to reflect the updated state in the UI.

useEffect Internals

  1. Effect Registration:

    • When a component renders, React processes the useEffect hook declarations.
    • It registers the effect function (effect) to be called after the component renders and the DOM is updated.
  2. Dependency Management:

    • If the useEffect hook has a dependency array ([]), React checks the dependencies after every render.
    • If any dependency has changed since the last render, React schedules the effect function (effect) to run after the component updates.
  3. Cleanup:

    • If the effect function (effect) returns a cleanup function, React saves it.
    • Before running the effect next time or before unmounting the component, React calls the cleanup function to clean up any resources used by the previous effect.
  4. Optimization:

    • React optimizes useEffect by running effects asynchronously after rendering, batching updates, and ensuring consistent timing.
    • It ensures that effects do not block the main thread, promoting smooth UI updates.

Example of Internal Behavior

Consider a simple example demonstrating useState and useEffect:

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

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

  useEffect(() => {
    // Effect function
    console.log('Effect: Component has rendered or updated');
    document.title = `Clicked ${count} times`; // Example of side effect
  }, [count]); // Dependency array: run effect only when `count` changes

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

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

export default Counter;


Published on: Jul 05, 2024, 06:29 AM  


Add your comment