mrkeyoor.com_
Fri 07 Aug 22:55 UTC
npmTestingupdated 07 Aug 2026

react-test-renderer

react-test-renderer renders a React tree to plain JavaScript objects instead of to the DOM or to native views, which is what made Jest snapshot testing of components possible before jsdom became the normal way to do it. You call create(<Component />), then toJSON() for a snapshot or root.findByType() to walk the tree by component type and props. Its own README now opens with a deprecation notice: the package is no longer maintained, it will be removed in a future React version, and React 19 prints a console warning when you call create(). The React team points at @testing-library/react instead.

Verdict

Deprecated by the React team, unmaintained, and warning on every render under React 19; the 8.3M weekly downloads are inertia from old suites, not a recommendation. Keep it only long enough to migrate to Testing Library.

API stability2/5The surface has not changed in years, which sounds good until you read the notice: the package is slated for removal in a future React version and 19 already warns on create(), so the stable API has an expiry date
Docs2/5The only reference is the test-renderer page on the archived legacy React docs site, since react.dev does not document it; the package README is mostly a deprecation notice plus one example
Maintenance1/5The README states plainly that it is deprecated and no longer maintained; versions keep appearing only because it is published alongside every React release from the same monorepo
Ecosystem2/58.3M weekly downloads reflect old Jest snapshot suites rather than current practice, and the tooling around React testing has moved to Testing Library, which this package's own documentation now recommends

Use it if

  • You have an existing snapshot suite built on it and need it to keep passing while you plan a migration
  • You are working on a custom React renderer or reconciler, where there is no DOM to render into and the object tree is the thing you want to assert on
  • You need to find nodes by component type or by props, which is exactly the internals-flavoured querying that DOM-based tools deliberately do not offer
  • You are on an older React version where the recommended replacements do not yet apply cleanly
Skip it if

Setup reality

Installing is unremarkable: the version tracks React itself, and the peer dependency pins it to the matching React major, so react-test-renderer 19.x needs react 19.x and a mismatch is an install error rather than a runtime surprise. What you actually spend time on is the missing DOM. Refs are called with null unless you supply createNodeMock, so any component that measures or focuses a node needs a hand-written stub per test. Anything asynchronous needs wrapping in act, which now comes from react itself rather than from this package. And the deprecation warning in React 19 lands on every create() call, so an existing suite goes noisy the moment you upgrade React, which is usually the moment teams discover they were still depending on this.

Patterns

Render a component to a JSON treesnapshot

import TestRenderer from 'react-test-renderer';

const testRenderer = TestRenderer.create(
  <Link page="https://example.com">Example</Link>
);

expect(testRenderer.toJSON()).toMatchSnapshot();

Under React 19 this call also prints a deprecation warning, once per create, to your test output.

Wrap updates in actact

import { act } from 'react';
import TestRenderer from 'react-test-renderer';

let testRenderer;
await act(async () => {
  testRenderer = TestRenderer.create(<Async />);
});

Import act from react, not from react-test-renderer; the re-export exists but is on the same deprecation path as the rest of the package.

Find a node by component typefind-by-type

const root = testRenderer.root;
const button = root.findByType(Button);

expect(button.props.disabled).toBe(true);

findByType throws when the match count is not exactly one; findAllByType is the version that returns an array.

Find nodes by their propsfind-by-props

const items = testRenderer.root.findAllByProps({ role: 'listitem' });
expect(items).toHaveLength(3);

This matches React props, not DOM attributes, which is precisely the internals coupling the deprecation notice warns about.

Trigger behaviour by calling a propinvoke-handler

import { act } from 'react';

const button = testRenderer.root.findByType(Button);
act(() => {
  button.props.onClick();
});

There are no synthetic events here, so you call the handler directly; nothing about bubbling, default prevention or disabled state is simulated.

Give refs something to point atnode-mock

const tree = TestRenderer.create(<TextareaAutosize />, {
  createNodeMock: (element) =>
    element.type === 'textarea'
      ? document.createElement('textarea')
      : null,
}).toJSON();

Without createNodeMock every ref callback receives null, which breaks any component that measures or focuses its own node.

Re-render with new propsupdate

testRenderer.update(<Counter count={2} />);
expect(testRenderer.toJSON()).toMatchSnapshot();

update re-renders the root in place, so state inside the tree survives; it is the equivalent of rerender in Testing Library.

Unmount and check cleanupunmount

testRenderer.unmount();
expect(clearIntervalSpy).toHaveBeenCalled();

Unmount in an afterEach or long suites leak timers and subscriptions between tests.

Get the tree with component nodes includedto-tree

const tree = testRenderer.toTree();
console.log(tree.type, tree.props, tree.rendered);

toJSON gives you host elements only; toTree keeps your own components in the output, and is heavier and more internals-flavoured for it.

Reach the class component instanceinstance

const instance = testRenderer.getInstance();
expect(instance.state.open).toBe(false);

Returns null for function components, which is most code now; reaching for it is a sign the test is asserting on implementation.

Keep the deprecation warning visible on purposesilence-warning

// jest.setup.js
const realError = console.error;
console.error = (...args) => {
  if (String(args[0]).includes('react-test-renderer is deprecated')) {
    return; // tracked in TICKET-123, remove this block when migrated
  }
  realError(...args);
};

If you must suppress it, tie the suppression to a ticket; a blanket console.error filter also hides the React warnings you do want to see.

What the same test looks like after migratingmigrate

import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

render(<Link page="https://example.com">Example</Link>);
await userEvent.click(screen.getByRole('link', { name: 'Example' }));

Queries move from component type to accessible role and text, which is the point: the test stops knowing your component structure.

Alternatives

PackageRegistryPick it when
@testing-library/reactnpmTesting web components the way the React team now recommends, against a real DOM with standard queries
@testing-library/react-nativenpmTesting React Native components, which is the replacement the deprecation notice names
jsdomnpmYou want the DOM environment the README points to and intend to assert with plain DOM APIs rather than a testing library