react-class-to-hooks
react-class-to-hooks rule
Keywords: React, hooks, migration, ESLint rule, class components, functional components, React modernization, auto-fix, LLM-optimized, React migration
Suggest migrating React class components to hooks with detailed migration path. This rule is part of eslint-plugin-react-features and provides LLM-optimized error messages with fix suggestions.
💡 Provides suggestions | 🔧 Automatically fixable
Quick Summary
| Aspect | Details |
|---|---|
| Severity | Warning (migration guidance) |
| Auto-Fix | ✅ Yes (suggests hooks migration) |
| Category | React / Migration |
| ESLint MCP | ✅ Optimized for ESLint MCP integration |
| Best For | React projects migrating from class to functional components |
Rule Details
Identifies React class components that can be migrated to functional components with hooks, providing complexity analysis and migration guidance.
Configuration
| Option | Type | Default | Description |
|---|---|---|---|
ignorePureRenderComponents | boolean | false | Ignore PureComponent classes |
allowComplexLifecycle | boolean | false | Allow complex lifecycle methods without warnings |
Examples
❌ Class Component
class UserProfile extends React.Component<Props, State> {
state = {
loading: false,
data: null
};
componentDidMount() {
this.fetchData();
}
fetchData = async () => {
this.setState({ loading: true });
const data = await api.getUser(this.props.userId);
this.setState({ data, loading: false });
};
render() {
const { loading, data } = this.state;
return loading ? <Spinner /> : <div>{data?.name}</div>;
}
}✅ Functional Component with Hooks
function UserProfile({ userId }: Props) {
const [loading, setLoading] = useState(false);
const [data, setData] = useState<User | null>(null);
useEffect(() => {
async function fetchData() {
setLoading(true);
const userData = await api.getUser(userId);
setData(userData);
setLoading(false);
}
fetchData();
}, [userId]);
return loading ? <Spinner /> : <div>{data?.name}</div>;
}Configuration Examples
{
rules: {
'react-features/react-class-to-hooks': ['warn', {
ignorePureRenderComponents: false,
allowComplexLifecycle: false
}]
}
}Lifecycle Method Mapping
| Class Lifecycle | Hook Equivalent |
|---|---|
componentDidMount | useEffect(() => {}, []) |
componentDidUpdate | useEffect(() => {}, [deps]) |
componentWillUnmount | useEffect(() => () => {}, []) |
shouldComponentUpdate | React.memo() |
getDerivedStateFromProps | useState + useEffect |
Comparison with Alternatives
| Feature | react-class-to-hooks | eslint-plugin-react-hooks | codemods |
|---|---|---|---|
| Class Detection | ✅ Yes | ❌ No | ✅ Yes |
| Migration Suggestions | ✅ Yes | ❌ No | ⚠️ Automated only |
| Auto-Fix | ✅ Yes | ❌ No | ✅ Yes |
| LLM-Optimized | ✅ Yes | ❌ No | ❌ No |
| ESLint MCP | ✅ Optimized | ❌ No | ❌ No |
| Complexity Analysis | ✅ Yes | ❌ No | ❌ No |
Related Rules
react-no-inline-functions- Performance optimizationrequired-attributes- React attribute enforcementno-deprecated-api- API modernization
Further Reading
- React Hooks Documentation - React hooks reference
- Migrating from Classes to Hooks - Migration guide
- React Codemods - Automated migration tools
- ESLint MCP Setup - Enable AI assistant integration
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 analyzedMitigation: Implement runtime validation and review code manually. Consider using TypeScript branded types for validated inputs.
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 trackedMitigation: Ensure imported values follow the same constraints. Use TypeScript for type safety.