react-hooks/incompatible-library

Report calls to library APIs that the React Compiler cannot memoize safely

The React Compiler reuses a value from the last render as long as its inputs are the same. A few libraries return objects and functions that stay the same while the data behind them changes. If they were memoized, they'd show stale data, so the compiler leaves every component and hook that calls one of them unoptimized. This rule tells you where that happens.

PackageWhat is reported
react-hook-formA call to the watch() that useForm() returns
@tanstack/react-tableuseReactTable()
@tanstack/react-virtualuseVirtualizer()

Configure#

Off by default. To turn it on:

bunfig.toml
[lint.rules]
"react-hooks/incompatible-library" = "error" # or "warn"

Examples#

Reported:

import { useForm } from "react-hook-form";

function Signup() {
  const { register, watch } = useForm();
  const email = watch("email");
  return <input {...register("email")} title={email} />;
}
import { useReactTable } from "@tanstack/react-table";
import { useVirtualizer } from "@tanstack/react-virtual";

function Table({ columns, data }) {
  const table = useReactTable({ columns, data });
  return <div>{table.getRowModel().rows.length} rows</div>;
}

function List({ rows, estimateSize }) {
  const virtualizer = useVirtualizer({ count: rows.length, estimateSize });
  return <div style={{ height: virtualizer.getTotalSize() }} />;
}

Not reported:

import { useForm, useWatch } from "react-hook-form";

function Signup() {
  const { register, control } = useForm();
  const email = useWatch({ control, name: "email" });
  return <input {...register("email")} title={email} />;
}

When not to use it#

If you don't build with the React Compiler, nothing is memoized for you and these APIs work as usual.