no-unstable-default-props
Rule category
Perf.
What it does
Prevents usage of referential-type values as default props in object destructuring.
Why is this bad?
When using object destructuring syntax you can set the default value for a given property if it does not exist. If you set the default value to one of the values that is compared by identity, then each time the destructuring is evaluated, the JS engine will create a new, distinct value in the destructured variable.
This harms performance as it means that React will have to re-evaluate hooks and re-render memoized components more often than necessary.
To fix the violations, the easiest way is to use a referencing variable in module scope instead of using the literal values.
Examples
Failing
import React from "react";
interface ExampleProps {
ExampleProps.items: string[]
items: string[];
}
function function Example({ items }: ExampleProps): null
Example({ items: string[]
items = [] }: ExampleProps) {
// - found a/an 'Array literal' as default prop. This could lead to potential infinite render loop in React. Use a variable instead of 'Array literal'.
return null;
}
import React from "react";
interface ExampleProps {
ExampleProps.items: Record<string, string>
items: type Record<K extends keyof any, T> = { [P in K]: T; }
Construct a type with a set of properties K of type TRecord<string, string>;
}
function function Example({ items }: ExampleProps): null
Example({ items: Record<string, string>
items = {} }: ExampleProps) {
// - found a/an 'Object literal' as default prop. This could lead to potential infinite render loop in React. Use a variable instead of 'Object literal'.
return null;
}
import React from "react";
interface ExampleProps {
ExampleProps.onClick: () => void
onClick: () => void;
}
function function Example({ onClick }: ExampleProps): null
Example({ onClick: () => void
onClick = () => {} }: ExampleProps) {
// - found a/an 'arrow function expression' as default prop. This could lead to potential infinite render loop in React. Use a variable instead of 'arrow function expression'.
return null;
}
import React from "react";
interface ExampleProps {
ExampleProps.items: string[]
items: string[];
}
function function Example(props: ExampleProps): null
Example(props: ExampleProps
props: ExampleProps) {
const { const items: string[]
items = [] } = props: ExampleProps
props;
// - found a/an 'Array literal' as default prop. This could lead to potential infinite render loop in React. Use a variable instead of 'Array literal'.
return null;
}
Passing
import React from "react";
const const emptyArray: string[]
emptyArray: string[] = [];
interface ExampleProps {
ExampleProps.items: string[]
items: string[];
}
function function Example({ items }: ExampleProps): null
Example({ items: string[]
items = const emptyArray: string[]
emptyArray }: ExampleProps) {
return null;
}
import React from "react";
const const emptyObject: {}
emptyObject = {};
interface ExampleProps {
ExampleProps.items: Record<string, string>
items: type Record<K extends keyof any, T> = { [P in K]: T; }
Construct a type with a set of properties K of type TRecord<string, string>;
}
function function Example({ items }: ExampleProps): null
Example({ items: Record<string, string>
items = const emptyObject: {}
emptyObject }: ExampleProps) {
return null;
}
import React from "react";
const const noop: () => void
noop = () => {};
interface ExampleProps {
ExampleProps.onClick: () => void
onClick: () => void;
}
function function Example({ onClick }: ExampleProps): null
Example({ onClick: () => void
onClick = const noop: () => void
noop }: ExampleProps) {
return null;
}
import React from "react";
const const emptyArray: string[]
emptyArray: string[] = [];
interface ExampleProps {
ExampleProps.items: string[]
items: string[];
}
function function Example(props: ExampleProps): null
Example(props: ExampleProps
props: ExampleProps) {
const { const items: string[]
items = const emptyArray: string[]
emptyArray } = props: ExampleProps
props;
return null;
}
import React from "react";
interface ExampleProps {
ExampleProps.num: number
num: number;
ExampleProps.str: string
str: string;
ExampleProps.bool: boolean
bool: boolean;
}
function function Example({ num, str, bool }: ExampleProps): null
Example({ num: number
num = 3, str: string
str = "foo", bool: boolean
bool = true }: ExampleProps) {Primitives are all compared by value, so are safe to be inlined return null;
}