logoESLint React
Rules

use-memo

This rule is currently in beta and only available in v3.0.0 beta releases.

Full Name in @eslint-react/eslint-plugin@beta

@eslint-react/use-memo

Full Name in eslint-plugin-react-x@beta

react-x/use-memo

Presets

x recommended recommended-typescript recommended-type-checked strict strict-typescript strict-type-checked

Description

Validates that useMemo is called with a callback that returns a value.

useMemo is designed for computing and caching expensive values between renders. Without a return value, useMemo always returns undefined, which defeats its purpose and likely indicates the wrong hook is being used.

There are two violations this rule catches:

  1. Missing return value — the callback passed to useMemo does not return a value (implicitly returns undefined).
  2. Result not assigned — the return value of useMemo is discarded (not assigned to a variable), which means the memoized value is never used.

If you need to run side effects when dependencies change, use useEffect instead.

Examples

Failing

// ❌ No return value in the callback
function Component({ data }) {
  const processed = useMemo(() => {
    data.forEach(item => console.log(item));
    // Missing return!
  }, [data]);
  return <div>{processed}</div>; // Always undefined
}
// ❌ useMemo result not assigned to a variable (side-effect usage)
function Component({ user }) {
  useMemo(() => {
    analytics.track("UserViewed", { userId: user.id });
  }, [user.id]);
  return <div />;
}
// ❌ useMemo result not assigned even when callback has a return
function Component({ user }) {
  useMemo(() => {
    return analytics.track("UserViewed", { userId: user.id });
  }, [user.id]);
  return <div />;
}

Passing

// ✅ Returns a computed value
function Component({ data }) {
  const processed = useMemo(() => {
    return data.map(item => item * 2);
  }, [data]);
  return <div>{processed}</div>;
}
// ✅ Arrow function with concise body (implicitly returns)
function Component({ items }) {
  const sorted = useMemo(() => [...items].sort(), [items]);
  return <div>{sorted.join(", ")}</div>;
}
// ✅ Use useEffect for side effects instead
function Component({ user }) {
  useEffect(() => {
    analytics.track("UserViewed", { userId: user.id });
  }, [user.id]);
  return <div />;
}

Implementation

Further Reading


See Also

On this page