new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

React · API reference · all subjects

eslint-plugin-react-hooks

160 notes in this subject, read out of this brain and free to use. This is page 3 of 3.

additionalEffectHooks ESLint configuration

Custom effect hooks can be configured using the 'react-hooks' shared ESLint settings with an 'additionalEffectHooks' property that accepts a regex pattern. This allows custom hooks like useEffectEvent to be treated as effects by both rules-of-hooks and exhaustive-deps rules. Available in eslint-plugin-react-hooks 6.1.1 and later.

use hook conditional example

The use hook can be called conditionally: `if (shouldFetch) { const data = use(fetchPromise); }` and can be called in loops: `for (const promise of promises) { results.push(use(promise)); }`

Hooks in conditions invalid example

This violates the Rules of Hooks: `if (isLoggedIn) { const [user, setUser] = useState(null); }`

Hooks after early return invalid example

This violates the Rules of Hooks: `if (!data) return <Loading />; const [processed, setProcessed] = useState(data);`

Hooks in callback invalid example

This violates the Rules of Hooks: `<button onClick={() => { const [clicked, setClicked] = useState(false); }}/>`

use hook in try/catch invalid example

This violates the Rules of Hooks: `try { const data = use(promise); } catch (e) { // error handling }`

Hooks at module level invalid example

This violates the Rules of Hooks: `const globalState = useState(0);` when called outside a component.

Valid hooks at top level example

This follows the Rules of Hooks: `function Component({ isSpecial, shouldFetch, fetchPromise }) { const [count, setCount] = useState(0); const [name, setName] = useState(''); if (!isSpecial) { return null; } if (shouldFetch) { const data = use(fetchPromise); return <div>{data}</div>; } return <div>{name}: {count}</div>; }`

Conditional useEffect fix example

Instead of `if (isLoggedIn) { useEffect(() => { fetchUserData(); }, []); }`, use: `useEffect(() => { if (isLoggedIn) { fetchUserData(); } }, [isLoggedIn]);`

Conditional state initialization fix example

Instead of conditionally calling useState for different scenarios, use: `const [permissions, setPermissions] = useState(userType === 'admin' ? adminPerms : userPerms);`

set-state-in-render: solution - enforce constraints in event handlers

Move clamping logic to event handlers where state is first set. Valid pattern: function Counter({max}) { const [count, setCount] = useState(0); const increment = () => { setCount(current => Math.min(current + 1, max)); }; return <button onClick={increment}>{count}</button>; } The setter only runs in response to the click, React finishes the render normally, and count never crosses max.

set-state-in-render rule: unconditional setState triggers infinite loops

The eslint-plugin-react-hooks rule 'set-state-in-render' validates against unconditionally setting state during render. Calling setState during render unconditionally triggers another render before the current one finishes, creating an infinite loop that crashes the app.

set-state-in-render: invalid pattern - unconditional setState in render

Unconditional setState directly in render is invalid. Example: function Component({value}) { const [count, setCount] = useState(0); setCount(value); return <div>{count}</div>; } This creates an infinite loop.

set-state-in-render: valid pattern - derive values during render

Instead of setting state unconditionally, derive values during render. Example: function Component({items}) { const sorted = [...items].sort(); return <ul>{sorted.map(/*...*/)} </ul>; }

set-state-in-render: valid pattern - setState in event handlers

Set state in event handlers instead of during render. Example: function Component() { const [count, setCount] = useState(0); return <button onClick={() => setCount(count + 1)}>{count}</button>; }

set-state-in-render: valid pattern - derive from props instead of setting state

Derive values from props instead of setting state. Example: function Component({user}) { const name = user?.name || ''; const email = user?.email || ''; return <div>{name}</div>; }

set-state-in-render: valid pattern - conditionally derive state from props

Conditionally set state from props and previous renders when a condition makes it valid. Example: function Component({ items }) { const [isReverse, setIsReverse] = useState(false); const [selection, setSelection] = useState(null); const [prevItems, setPrevItems] = useState(items); if (items !== prevItems) { setPrevItems(items); setSelection(null); } ... } The condition checking that items changed makes this valid.

set-state-in-render: pitfall - clamping state during render causes infinite loop

Attempting to clamp state during render causes an infinite loop. Invalid pattern: function Counter({max}) { const [count, setCount] = useState(0); if (count > max) { setCount(max); } return <button onClick={() => setCount(count + 1)}>{count}</button>; } As soon as count exceeds max, an infinite loop is triggered.

static-components rule validates components are not recreated every render

The static-components ESLint rule from eslint-plugin-react-hooks validates that components are static and not recreated on every render. Components that are recreated dynamically can reset state and trigger excessive re-rendering.

Components defined inside other components are recreated every render

When a component is defined inside another component, it is recreated on every render. React sees each instance as a brand new component type, unmounting the old one and mounting the new one, which destroys all state and DOM nodes in the process.

static-components invalid pattern: component defined inside parent

Defining a component inside a parent component causes the child component to be recreated every render, resetting its state. Example: function Parent() { const ChildComponent = () => { const [count, setCount] = useState(0); return <button onClick={() => setCount(count + 1)}>{count}</button>; }; return <ChildComponent />; }

static-components invalid pattern: dynamic component creation

Creating different components conditionally based on props causes those components to be recreated every render. Example: function Parent({type}) { const Component = type === 'button' ? () => <button>Click</button> : () => <div>Text</div>; return <Component />; }

static-components valid pattern: reference existing components

Define components at module level and reference them by name instead of creating them dynamically. Example: const ButtonComponent = () => <button>Click</button>; const TextComponent = () => <div>Text</div>; function Parent({type}) { const Component = type === 'button' ? ButtonComponent : TextComponent; return <Component />; }

static-components solution: pass data as props instead of defining components inside

Instead of defining a component inside a parent component to access parent state, pass the data as props to a static component. This makes components more reusable and testable. Example: function ThemedButton({theme}) { return <button className={theme}>Click me</button>; } function Parent() { const [theme, setTheme] = useState('light'); return <ThemedButton theme={theme} />; }

Example: eval in component should use safe parser instead

Invalid: function Calculator({expression}) { const result = eval(expression); return <div>Result: {result}</div>; } Valid: import {evaluate} from 'mathjs'; function Calculator({expression}) { const [result, setResult] = useState(null); const calculate = () => { try { setResult(evaluate(expression)); } catch (error) { setResult('Invalid expression'); } }; return ( <div> <button onClick={calculate}>Calculate</button> {result && <div>Result: {result}</div>} </div> ); } This example shows how to safely evaluate user-provided mathematical expressions using a dedicated library instead of eval.

unsupported-syntax rule validates against React Compiler incompatible syntax

The unsupported-syntax rule validates against syntax that React Compiler does not support. Features like eval and with statements make it impossible for the compiler to statically analyze code at compile time, so components using them cannot be optimized. The rule allows using such syntax outside of React, such as in standalone utility functions.

eval in components cannot be analyzed by React Compiler

Using eval() in a component is invalid because the React Compiler cannot statically analyze what code eval executes at compile time. This prevents the compiler from applying optimizations.

with statement changes scope dynamically and cannot be analyzed

Using a with statement in a component is invalid because it changes scope dynamically in ways that cannot be statically understood by the React Compiler.

Dynamic property access with computed keys is analyzable

Use computed property access like props[propName] instead of eval for dynamic property access. Computed property access can be statically analyzed by React Compiler.

Never use eval with user input - it is a security risk

Using eval with user-provided input is both a security risk and makes code unoptimizable. Instead, use dedicated parsing libraries for specific use cases like mathematical expressions, JSON parsing, or template evaluation.

use-memo lint rule validates return value requirement

The use-memo eslint-plugin-react-hooks lint rule validates that the useMemo hook is used with a return value. useMemo is for computing and caching expensive values, not for side effects. Without a return value, useMemo returns undefined, which defeats its purpose and indicates you are using the wrong hook.

useMemo without return value is an error

A useMemo callback that does not return a value is invalid. For example, iterating over data with forEach and logging items without a return statement means useMemo returns undefined, making the hook pointless. This pattern indicates you should use useEffect instead.

useMemo correct usage example with return value

Example of correct useMemo usage: function Component({ data }) { const processed = useMemo(() => { return data.map(item => item * 2); }, [data]); return <div>{processed}</div>; } The callback must return a computed value that is then assigned to a variable.

Do not use useMemo for side effects

useMemo should not be used to perform side effects. Side effects in useMemo are wrong because the hook is designed for computing and caching values, not for running code for its effects. If a side effect needs to happen in response to user interaction, colocate it with the event handler. If a side effect synchronizes React state with external state, use useEffect instead.

useMemo side effect antipattern examples

Incorrect useMemo patterns for side effects: 1. No return value, just side effect: useMemo(() => { analytics.track('UserViewed', {userId: user.id}); }, [user.id]); 2. Returning the side effect result without assigning to variable: useMemo(() => { return analytics.track('UserViewed', {userId: user.id}); }, [user.id]); Both patterns indicate useMemo is being misused for side effects rather than value computation.

Use useEffect for synchronizing React state with external state

When a side effect needs to synchronize React state with some external state or vice versa, use useEffect instead of useMemo. For example, to persist theme preference to localStorage and update the DOM when theme changes: useEffect(() => { localStorage.setItem('preferredTheme', theme); document.body.className = theme; }, [theme]);

Use event handlers for side effects from user interaction

When a side effect needs to happen in response to user interaction, colocate the side effect with the event handler. For example: const handleClick = () => { analytics.track('ButtonClicked', {userId: user.id}); // Other click logic... }; return <button onClick={handleClick}>Click me</button>;

ESLint Plugin React Hooks purpose

The ESLint plugin for React Hooks helps enforce the Rules of React, with detailed documentation for each lint including examples.

eslint-plugin-react-hooks enforcement for useEffectEvent

The eslint-plugin-react-hooks linter enforces the restrictions on Effect Events: they can only be called from inside Effects or other Effect Events, not during rendering or passed to other components or Hooks.

eslint-plugin-react-hooks for catching rule violations

The eslint-plugin-react-hooks plugin can be used to catch violations of the Rules of Hooks.

Give your agent this brain