purity
Validates that components and hooks are pure by checking that they do not call known-impure functions during render.
This is an evaluation implementation and may contain false positives or negatives that have not yet been fully audited. Review each report carefully before applying fixes.
Full Name in eslint-plugin-react-x
react-x/purityFull Name in @eslint-react/eslint-plugin
@eslint-react/purityPresets
x
recommended
recommended-typescript
recommended-type-checked
strict
strict-typescript
strict-type-checked
Rule Details
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.
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()
Examples
Generating random values during render
Random values change on every render, making the component's output unpredictable. This breaks memoization and can cause hydration mismatches in server-rendered apps.
// Problem: produces a different value on every render
function Component() {
const id = Math.random(); // different on every render
// ^^^ 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>;
}// Problem: calling crypto.randomUUID() directly during render
function Component() {
const id = crypto.randomUUID(); // different on every render
// ^^^ Do not call 'crypto.randomUUID()' during render. Components and hooks must be pure. Move this call into an event handler, effect, or state initializer.
return <div id={id}>Content</div>;
}// Recommended: use lazy initialization to ensure a stable value
function Component() {
const [id] = useState(() => crypto.randomUUID());
return <div key={id}>Content</div>;
}// Problem: useMemo cannot make an impure call pure
function Component() {
const value = useMemo(() => 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>{value}</div>;
}Using time-based values during render
Time-based values change constantly. Using them directly in render makes the component impure and causes unnecessary re-renders or hydration issues.
// Problem: time-based value changes on every render
function Component() {
const timestamp = Date.now(); // constantly changing
// ^^^ 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>;
}// Problem: new Date() is also impure
function Component() {
const date = new Date(); // new time on every render
// ^^^ 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>;
}// Recommended: use time-based values in effects or event handlers
function Component() {
useEffect(() => {
const timestamp = Date.now();
console.log(timestamp);
}, []);
return <div>Content</div>;
}Using time-based values in custom hooks
Custom hooks are also part of the render phase, so impure calls inside them are flagged just like in components.
// Problem: impure call inside a custom hook
function useTimestamp() {
const t = Date.now(); // called during render
// ^^^ 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;
}// Recommended: move impure logic into an effect
function useTimestamp() {
const [timestamp, setTimestamp] = useState(() => Date.now());
useEffect(() => {
setTimestamp(Date.now());
}, []);
return timestamp;
}Impure calls in event handlers and effects
Event handlers and effects run outside of React's render cycle, so impure functions are perfectly acceptable there.
// Recommended: use random numbers in event handlers
function Component() {
return (
<button onClick={() => console.log(Math.random())}>
Roll
</button>
);
}// Recommended: use timestamps in effects
function Component() {
useEffect(() => {
const timestamp = Date.now();
console.log(timestamp);
}, []);
return <div>Content</div>;
}Showing the current time
Calling Date.now() directly in JSX produces a different value on every render and makes the component impure.
// Problem: time changes on every render
function Clock() {
return <div>Current time: {Date.now()}</div>;
}When you need to display a constantly updating value like the current time, use state and an effect rather than calling Date.now() directly in render.
// Recommended: manage time with state and effects
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>;
}Versions
Resources
Further Reading
- React Docs: Keeping Components Pure
- React Docs: Components and Hooks must be pure
- React Docs:
purityLint Rule
See Also
react-x/rules-of-hooks
Enforces the Rules of Hooks.react-x/unsupported-syntax
Validates against syntax that React Compiler does not support.