DEV Community

Cover image for React 18 - useTransition hook
Moises Marques da Silva
Moises Marques da Silva

Posted on • Updated on

React 18 - useTransition hook

In March 2022 React 18 was launched with some new interesting features, in this article we'll talk about the one of the 5 new hooks on React, the useTransition hook.

useTransition

This hook is used to control the timing of state changes that could occur based on user interactions. Simply put, useTransition hook enables state updates to occur in a way that is less blocking for user inputs resulting in a smoother user experience.

Benefits of useTransition

Improved User Experience: By using useTransition, developers can ensure that the application remains responsive and interactive during resource-intensive tasks, leading to a better overall user experience.
Smooth Animations: With useTransition, you can create smooth animations that run seamlessly, without blocking the user interface.

Better Performance: By deferring rendering and updates, the useTransition hook helps prevent unnecessary re-renders and optimizes performance.
Enhanced Code Maintainability: useTransition simplifies the management of complex animations and transitions, making the codebase cleaner and more maintainable.

Example: Infinite Scrolling with useTransition

Imagine you have a web application that displays a list of items retrieved from an API. As the user scrolls down, the application fetches additional data to load more items dynamically.

To provide a smooth user experience, you want to use the useTransition hook to handle the loading state and animations during data fetching.

Step 1: Create the app

Open VS Code and run the command bellow:

npx create-react-app infinity-scroll-app
Enter fullscreen mode Exit fullscreen mode

Step 2: Write the following code on App.js

import React, { useState, useEffect, useTransition, useCallback } from "react";
import "./App.css";
import dummyData from "./dummyData"; // Assuming the file path is correct

function App() {
  const [items, setItems] = useState([]);
  const [page, setPage] = useState(1);
  const [isFetching, setIsFetching] = useState(false);
  const [isPending, startTransition] = useTransition();

  const getItemsFromPage = (currentPage) => {
    const itemsPerPage = 10; // You can adjust the number of items per page
    const startIndex = (currentPage - 1) * itemsPerPage;
    const endIndex = startIndex + itemsPerPage;
    return dummyData.slice(startIndex, endIndex);
  };

  const fetchMoreData = useCallback(() => {
    startTransition(() => {
      setItems((prevItems) => [...prevItems, ...getItemsFromPage(page)]);
      setIsFetching(false);
    });
  }, [page, startTransition]);

  useEffect(() => {
    if (isFetching) {
      fetchMoreData();
    }
  }, [fetchMoreData, isFetching]);

  const handleScroll = () => {
    const windowHeight = window.innerHeight;
    const documentHeight = document.documentElement.scrollHeight;
    const scrollTop = window.scrollY;

    if (scrollTop + windowHeight >= documentHeight) {
      setIsFetching(true);
      setPage((prevPage) => prevPage + 1);
    }
  };

  useEffect(() => {
    fetchMoreData();
    window.addEventListener("scroll", handleScroll);
    return () => window.removeEventListener("scroll", handleScroll);
  }, [fetchMoreData]);

  return (
    <div>
      <table className="table">
        <thead>
          <tr>
            <th>Name</th>
            <th>Age</th>
            <th>Country</th>
          </tr>
        </thead>
        <tbody>
          {items.map((item, index) => (
            <tr key={item._id}>
              <td>{item.name}</td>
              <td>{item.age}</td>
              <td>{item.country}</td>
            </tr>
          ))}
        </tbody>
      </table>
      {isPending && <div>Loading more items...</div>}
    </div>
  );
}

export default App;

Enter fullscreen mode Exit fullscreen mode

Top comments (0)