How to Use React Testing Library: Simple Guide with Examples
To use
React Testing Library, import its functions like render and screen to render components and query elements. Write tests by rendering your component and asserting expected behavior using queries and user events.Syntax
React Testing Library provides simple functions to render components and find elements for testing. The main functions are:
render(component): Renders the React component for testing.screen: Provides queries to find elements by text, role, label, etc.fireEventoruserEvent: Simulates user actions like clicks or typing.expect: Used with Jest to assert conditions.
Use these together to write tests that check how your component behaves.
javascript
import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; // Render a component render(<MyComponent />); // Find an element by text const button = screen.getByText('Click me'); // Simulate a click await userEvent.click(button); // Assert expected result expect(screen.getByText('Clicked')).toBeInTheDocument();
Example
This example shows a simple button component that changes text when clicked. The test renders the button, clicks it, and checks the changed text.
javascript
import React, { useState } from 'react'; import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; default function ClickButton() { const [clicked, setClicked] = useState(false); return ( <button onClick={() => setClicked(true)}> {clicked ? 'Clicked' : 'Click me'} </button> ); } test('button changes text when clicked', async () => { render(<ClickButton />); const button = screen.getByText('Click me'); await userEvent.click(button); expect(screen.getByText('Clicked')).toBeInTheDocument(); });
Output
PASS button changes text when clicked
Common Pitfalls
Common mistakes when using React Testing Library include:
- Not using
screenqueries and instead querying from the render result, which is less readable. - Using
getByqueries without handling the case when elements are not found, causing tests to fail unexpectedly. - Not waiting for asynchronous updates with
findByorwaitFor. - Testing implementation details like component state instead of user-visible behavior.
Always test what the user sees and interacts with, not internal details.
javascript
/* Wrong way: querying from render result */ const { getByText } = render(<MyComponent />); const button = getByText('Submit'); /* Better way: use screen for clarity */ render(<MyComponent />); const button = screen.getByText('Submit');
Quick Reference
| Function | Purpose |
|---|---|
| render(component) | Render a React component for testing |
| screen.getByText(text) | Find element by visible text |
| screen.getByRole(role) | Find element by ARIA role |
| userEvent.click(element) | Simulate user click |
| expect(value).toBeInTheDocument() | Assert element is present |
| findBy / waitFor | Wait for async elements or updates |
Key Takeaways
Use React Testing Library's render and screen to test components like a user would see them.
Simulate user actions with userEvent for realistic interaction testing.
Avoid testing internal implementation; focus on visible behavior and accessibility.
Use async queries like findBy or waitFor for components with delayed updates.
Prefer screen queries over destructured render queries for clearer tests.