purity
Full Name in @eslint-react/eslint-plugin@beta
@eslint-react/purityFull Name in eslint-plugin-react-x@beta
react-x/purityPresets
x
recommended
recommended-typescript
recommended-type-checked
strict
strict-typescript
strict-type-checked
Description
Validates that components and hooks are pure by checking that they do not call known-impure functions during render.
React components must be pure functions — given the same props, they should always return the same JSX. When components use functions like Math.random() or Date.now() during render, they produce different output each time, breaking React's assumptions and causing bugs like hydration mismatches, incorrect memoization, and unpredictable behavior.
Common Violations
In general, any API that returns a different value for the same inputs violates this rule. Usual examples include:
Math.random()Date.now()/new Date()crypto.randomUUID()/crypto.getRandomValues()performance.now()
Invalid
// ❌ Math.random() in render
function Component() {
const id = Math.random(); // Different every render
return <div key={id}>Content</div>;
}// ❌ Date.now() for values
function Component() {
const timestamp = Date.now(); // Changes every render
return <div>Created at: {timestamp}</div>;
}// ❌ new Date() in render
function Component() {
const date = new Date(); // Different every render
return <div>{date.toISOString()}</div>;
}Valid
// ✅ Stable IDs from initial state
function Component() {
const [id] = useState(() => crypto.randomUUID());
return <div key={id}>Content</div>;
}// ✅ Impure calls in event handlers
function Component() {
return (
<button onClick={() => console.log(Math.random())}>
Roll
</button>
);
}// ✅ Impure calls inside effects
function Component() {
useEffect(() => {
const timestamp = Date.now();
console.log(timestamp);
}, []);
return <div>Content</div>;
}Troubleshooting
I need to show the current time
Calling Date.now() during render makes your component impure:
// ❌ Wrong: Time changes every render
function Clock() {
return <div>Current time: {Date.now()}</div>;
}Instead, move the impure function outside of render:
// ✅ Correct: Initialize in state, update in effect
function Clock() {
const [time, setTime] = useState(() => Date.now());
useEffect(() => {
const interval = setInterval(() => {
setTime(Date.now());
}, 1000);
return () => clearInterval(interval);
}, []);
return <div>Current time: {time}</div>;
}I need a unique ID
Calling crypto.randomUUID() or Math.random() during render produces a different value on every render:
// ❌ Wrong: ID changes every render
function Component() {
const id = crypto.randomUUID();
return <div id={id}>Content</div>;
}Instead, wrap the call in a state initializer so it only runs once:
// ✅ Correct: ID is stable across renders
function Component() {
const [id] = useState(() => crypto.randomUUID());
return <div id={id}>Content</div>;
}Examples
Failing
function Component() {
const id = Math.random();
// ^^^^^^^^^^^^^
// - Do not call 'Math.random()' during render. Components and hooks must be pure.
// Move this call into an event handler, effect, or state initializer.
return <div key={id}>Content</div>;
}function Component() {
const timestamp = Date.now();
// ^^^^^^^^^^
// - Do not call 'Date.now()' during render. Components and hooks must be pure.
// Move this call into an event handler, effect, or state initializer.
return <div>Created at: {timestamp}</div>;
}function Component() {
const date = new Date();
// ^^^^^^^^^^
// - Do not call 'new Date()' during render. Components and hooks must be pure.
// Move this call into an event handler, effect, or state initializer.
return <div>{date.toISOString()}</div>;
}function useTimestamp() {
const t = Date.now();
// ^^^^^^^^^^
// - Do not call 'Date.now()' during render. Components and hooks must be pure.
// Move this call into an event handler, effect, or state initializer.
return t;
}Passing
function Component() {
const [id] = useState(() => crypto.randomUUID());
return <div key={id}>Content</div>;
}function Component() {
return (
<button onClick={() => console.log(Math.random())}>
Roll
</button>
);
}function Component() {
useEffect(() => {
const timestamp = Date.now();
console.log(timestamp);
}, []);
return <div>Content</div>;
}function Component() {
const value = useMemo(() => Math.random(), []);
return <div>{value}</div>;
}