react-perf/jsx-no-new-array-as-prop
Disallow arrays created during render as the value of a JSX prop
Also called react_perf/jsx-no-new-array-as-prop
[] written inside a component makes a new array on every render. When you pass it as a prop, it's never equal to the value from the last render, so a child wrapped in React.memo renders again even though the contents are the same.
The rule reports array literals, Array(), new Array(), and calls to .concat(), .map() and .filter() with one argument. An array at the top level of a module isn't reported, because it's created once.
Configure#
Off by default. To turn it on:
[lint.rules]
"react-perf/jsx-no-new-array-as-prop" = "error" # or "warn"Every option, set to its default:
[lint.rules]
"react-perf/jsx-no-new-array-as-prop" = ["error", {
nativeAllowList = [], # list of strings
}]Examples#
function Settings() {
return <Select options={["light", "dark"]JSX attribute values should not contain Arrays created in the same scope.} />;
}function Inbox({ messages }) {
return <List items={messages.filter((message) => !message.read)JSX attribute values should not contain Arrays created in the same scope.} />;
}The rule looks into ||, &&, ?? and ? ::
function Inbox({ messages }) {
return <List items={messages || []JSX attribute values should not contain Arrays created in the same scope.} />;
}A variable declared inside the component has the same problem as an array written in the prop, and so does a destructured prop's default. The report is on the declaration:
function Inbox({ messagesJSX attribute values should not contain Arrays created in the same scope. = [] }) {
const columnsJSX attribute values should not contain Arrays created in the same scope. = ["from", "subject"];
return <List items={messages} columns={columns} />;
}const themes = ["light", "dark"];
const none = [];
function Settings() {
return <Select options={themes} />;
}
function Inbox({ messages }) {
return <List items={messages || none} />;
}If the array depends on props or state, cache it with useMemo:
import { useMemo } from "react";
function Inbox({ messages }) {
const unread = useMemo(() => messages.filter((message) => !message.read), [messages]);
return <List items={unread} />;
}Options#
| Option | Default | What it does |
|---|---|---|
nativeAllowList | [] | Props to skip on elements with a lowercase name, such as <div>. A list of prop names (case doesn't matter), or "all" for every prop. |
With { "nativeAllowList": ["points"] }, this is allowed:
{ "nativeAllowList": ["points"] }No problemsfunction Report() {
return <my-chart points={[1, 2, 3]} />;
}Components are still checked:
{ "nativeAllowList": ["points"] }1 problemfunction Report() {
return <Chart points={[1, 2, 3]JSX attribute values should not contain Arrays created in the same scope.} />;
}When not to use it#
A new prop value only matters to a child that compares its props, for example with React.memo. The React Compiler memoizes these values for you.