react-hooks/memo-dependencies
Require the dependency list of useMemo and useCallback to match what the callback reads
Also called react_hooks/memo-dependencies, react/memo-dependencies
useMemo and useCallback keep their result until a value in the dependency list changes. If the callback reads a value that isn't in the list, the result stays the same when that value changes, and the component shows old data. A value in the list that the callback doesn't read makes it run again for nothing.
You don't have to list values that never change between renders, such as a setState function or a ref.
In .ts and .tsx files, the report comes with a suggestion that rewrites the list, which your editor can apply.
Configure#
Off by default. To turn it on:
[lint.rules]
"react-hooks/memo-dependencies" = "error" # or "warn"Examples#
Reported, because query is missing from the list:
import { useMemo } from "react";
function Results({ items, query }) {
const visible = useMemo(() => items.filter(item => item.name.includes(queryError: Found missing memoization dependenciesMissing dependencies can cause a value to update less often than it should, resulting in stale UI.)), [items]);
return <List items={visible} />;
}Reported, because the callback doesn't read theme:
import { useCallback } from "react";
function SaveButton({ save, draft, theme }) {
const onClick = useCallback(() => save(draft), [save, draft, themeError: Found extra memoization dependenciesExtra dependencies can cause a value to update more often than it should, resulting in performance problems such as excessive renders or effects firing too often.]);
return <button onClick={onClick}>Save</button>;
}import { useCallback, useMemo, useState } from "react";
function Results({ items, query }) {
const [selected, setSelected] = useState(null);
const visible = useMemo(() => items.filter(item => item.name.includes(query)), [items, query]);
const onSelect = useCallback(item => setSelected(item.id), []);
return <List items={visible} selected={selected} onSelect={onSelect} />;
}When not to use it#
react-hooks/exhaustive-deps checks the same two hooks, and effects too. With both rules on, the same list is reported twice.