0
0
ReactHow-ToBeginner · 4 min read

How to Test Loading State in React Components

To test a loading state in React, render the component and check if the loading indicator (like a spinner or text) appears before the data loads. Use React Testing Library's screen and waitFor to assert the loading UI shows and then disappears when loading finishes.
📐

Syntax

Testing loading state involves rendering the component, checking for the loading indicator, and waiting for the final content to appear.

  • render(): Render the React component.
  • screen.getByText(): Find the loading text or spinner.
  • waitFor(): Wait for the loading to finish and content to appear.
javascript
import { render, screen, waitFor } from '@testing-library/react';

render(<MyComponent />);
expect(screen.getByText(/loading/i)).toBeInTheDocument();
await waitFor(() => expect(screen.getByText(/data loaded/i)).toBeInTheDocument());
💻

Example

This example shows a component that fetches data and displays a loading message while waiting. The test checks that the loading message appears first, then the data is shown.

javascript
import React, { useEffect, useState } from 'react';
import { render, screen, waitFor } from '@testing-library/react';

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

  useEffect(() => {
    setTimeout(() => {
      setData('Data loaded');
      setLoading(false);
    }, 500);
  }, []);

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

// Test
test('shows loading then data', async () => {
  render(<DataLoader />);

  // Check loading state
  expect(screen.getByText(/loading/i)).toBeInTheDocument();

  // Wait for data to appear
  await waitFor(() => expect(screen.getByText(/data loaded/i)).toBeInTheDocument());
});
Output
Loading... (initially visible) Data loaded (visible after 500ms)
⚠️

Common Pitfalls

Common mistakes when testing loading states include:

  • Not waiting for the loading to finish, causing tests to fail.
  • Checking for loading text after it disappears.
  • Using findByText without understanding it waits automatically.

Always use waitFor or findBy queries to handle async UI changes.

javascript
/* Wrong: Checking loading after it disappears */
render(<DataLoader />);
expect(screen.queryByText(/loading/i)).toBeInTheDocument(); // Fails if loading is gone

/* Right: Check loading first, then wait for data */
expect(screen.getByText(/loading/i)).toBeInTheDocument();
await waitFor(() => expect(screen.getByText(/data loaded/i)).toBeInTheDocument());
📊

Quick Reference

  • Use render() to mount the component.
  • Use screen.getByText() to check loading UI immediately.
  • Use waitFor() or findByText() to wait for async updates.
  • Do not check for loading after it should be gone without waiting.

Key Takeaways

Always check the loading indicator appears before data loads.
Use waitFor or findBy queries to handle asynchronous UI changes.
Avoid checking for loading text after it disappears without waiting.
Render the component fresh for each test to avoid state leaks.
Keep tests simple: check loading, then check final content.