Skip to main content
ESLint Interlace
Plugin: react-featuresRules

no-set-state

no-set-state rule

Keywords: React, setState, hooks, functional components, migration, useState, ESLint rule, LLM-optimized

Disallow usage of setState to encourage functional components with hooks. This rule is part of eslint-plugin-react-features.

Quick Summary

AspectDetails
SeverityWarning (modernization)
Auto-Fix❌ No (requires component refactor)
CategoryReact
ESLint MCP✅ Optimized for ESLint MCP integration
Best ForProjects migrating to hooks

Rule Details

This rule flags all usages of setState to encourage migration to functional components with the useState hook. Hooks provide a cleaner API for state management.

Why This Matters

IssueImpactSolution
🔄 Verbose syntaxMore boilerplate codeUse useState hook
🐛 Complex this bindingCommon source of bugsHooks avoid this
🔍 Logic reuseHard to share stateful logicCustom hooks enable reuse

Examples

❌ Incorrect

class Counter extends React.Component {
  state = { count: 0 };
  
  increment = () => {
    // BAD: Using setState in class component
    this.setState({ count: this.state.count + 1 });
    
    // Also flagged
    this.setState(prevState => ({
      count: prevState.count + 1
    }));
  };
  
  render() {
    return (
      <button onClick={this.increment}>
        Count: {this.state.count}
      </button>
    );
  }
}

✅ Correct

// GOOD: Functional component with useState
function Counter() {
  const [count, setCount] = useState(0);
  
  const increment = useCallback(() => {
    setCount(c => c + 1);
  }, []);
  
  return (
    <button onClick={increment}>
      Count: {count}
    </button>
  );
}

// GOOD: Complex state with useReducer
function TodoList() {
  const [state, dispatch] = useReducer(todoReducer, initialState);
  
  const addTodo = useCallback((text) => {
    dispatch({ type: 'ADD_TODO', payload: text });
  }, []);
  
  return <TodoItems items={state.todos} onAdd={addTodo} />;
}

Configuration Examples

Basic Usage

{
  rules: {
    'react-features/no-set-state': 'warn'
  }
}

Strict (for new projects)

{
  rules: {
    'react-features/no-set-state': 'error'
  }
}

Further Reading

Known False Negatives

The following patterns are not detected due to static analysis limitations:

Dynamic Variable References

Why: Static analysis cannot trace values stored in variables or passed through function parameters.

// ❌ NOT DETECTED - Prop from variable
const propValue = computedValue;
<Component prop={propValue} /> // Computation not analyzed

Mitigation: Implement runtime validation and review code manually. Consider using TypeScript branded types for validated inputs.

Wrapped or Aliased Functions

Why: Custom wrapper functions or aliased methods are not recognized by the rule.

// ❌ NOT DETECTED - Custom wrapper
function myWrapper(data) {
  return internalApi(data); // Wrapper not analyzed
}
myWrapper(unsafeInput);

Mitigation: Apply this rule's principles to wrapper function implementations. Avoid aliasing security-sensitive functions.

Imported Values

Why: When values come from imports, the rule cannot analyze their origin or construction.

// ❌ NOT DETECTED - Value from import
import { getValue } from './helpers';
processValue(getValue()); // Cross-file not tracked

Mitigation: Ensure imported values follow the same constraints. Use TypeScript for type safety.