Try @eslint-react/kit@beta โ†’
logoESLint React

no-unused-state

Warns about state variables that are defined but never used, or only used in effects.

This rule is experimental and may change in the future or be removed. It is not recommended for use in production code at this time.

Full Name in eslint-plugin-react-x

react-x/no-unused-state

Full Name in @eslint-react/eslint-plugin

@eslint-react/no-unused-state

Features

๐Ÿงช

Rule Details

This rule warns about state variables declared via useState (or similar state hooks) that are defined but never read, or only read inside an effect or effect dependency array. State that is only used in effects often indicates missing logic in the render output or a state value that can be derived from props instead.

Examples

State declared but never read in the component

If only useState is called and the setter is destructured, but the state value itself is never read, this state has no actual effect on rendering.

// Problem: data is declared but never read
import { useState } from "react";

function Component() {
  const [data, setData] = useState(0);
  return <div />;
}
// Recommended: remove the state if it is not needed; otherwise use it in JSX
import { useState } from "react";

function Component() {
  const [data, setData] = useState(0);
  return <div>{data}</div>;
}

State only read in an effect

If a state value is only used inside useEffect (including the dependency array), it often means it could be computed directly during rendering, or does not need to exist as state at all.

// Problem: data is only read in an effect
import { useEffect, useState } from "react";

function Component() {
  const [data, setData] = useState(0);
  useEffect(() => {
    console.log(data);
  }, [data]);
  return <div />;
}
// Recommended: move the logic into rendering or compute directly from props
import { useCallback, useState } from "react";

function Component() {
  const [data, setData] = useState(0);
  const handleClick = useCallback(() => {
    console.log(data);
  }, [data]);
  return <div onClick={handleClick} />;
}

Simulating computed properties with state and effects

When a state value can be fully computed from props, using useState + useEffect is redundant. It adds unnecessary code and introduces extra render cycles.

// Problem: fullName can be fully computed from props
import { useEffect, useState } from "react";

function Form({ firstName, lastName }) {
  const [fullName, setFullName] = useState("");
  useEffect(() => {
    setFullName(firstName + " " + lastName);
  }, [firstName, lastName]);
  // ...
}
// Recommended: compute directly during rendering
function Form({ firstName, lastName }) {
  const fullName = firstName + " " + lastName;
  // ...
}

Options

Shared Settings

Custom state and effect hooks can also be configured via shared ESLint settings, which apply consistently across all rules in the plugin:

{
  "settings": {
    "react-x": {
      "additionalStateHooks": "/^(useMyState|useCustomState)$/u",
      "additionalEffectHooks": "/^(useMyEffect|useCustomEffect)$/u",
    }
  }
}

Versions

Resources

Further Reading

On this page