Skip to content

feat: add class-to-functional-migration skill#12

Open
HassamAzam wants to merge 1 commit into
arbisoft:mainfrom
HassamAzam:feature/hassam/class-to-functional-skill
Open

feat: add class-to-functional-migration skill#12
HassamAzam wants to merge 1 commit into
arbisoft:mainfrom
HassamAzam:feature/hassam/class-to-functional-skill

Conversation

@HassamAzam
Copy link
Copy Markdown

What

Adds a new skill Claude/skills/class-to-functional-migration/ for converting React class components into functional components with hooks.

Why

Class-to-hook conversion is one of the most common React refactors and is easy to get subtly wrong (stale closures, missing effect deps, identity churn, dropped cleanup). This skill gives the agent a strict, behavior-preserving workflow with concrete before/after code for every class construct so the conversion does not regress behavior.

What's in the skill

  • Pre-Migration Audit — list state, lifecycle, refs, instance fields, HOCs, and forwardRef usage before touching code
  • Conversion Map with before/after snippets for: state, lifecycle methods, refs and instance fields, class methods, derived values, HOCs (connect, withRouter, withTranslation, withTheme/withStyles), forwardRef + useImperativeHandle
  • Lifecycle → hook quick-reference table including the cases hooks cannot replace (componentDidCatch)
  • 6-step workflow — Audit → Convert → Correctness → Performance → Maintainability → Validate
  • Common Pitfalls — stale closures, missing effect deps, object/function identity churn, useEffect for derived state, useRef misuse, missing cleanup
  • Output Expectations and Constraints sections so the agent's deliverable is predictable

Quality checklist

  • File is placed in the correct directory (Claude/skills/class-to-functional-migration/SKILL.md)
  • Filename and name field follow kebab-case
  • YAML frontmatter is present and valid (name, description, origin)
  • Under the 500-line SKILL.md limit (331 lines)
  • Content is generic — no project-specific references
  • No sensitive information

A behavior-preserving workflow for converting React class components to functional components with hooks. Covers state, lifecycle, refs, methods, derived values, HOCs, and forwardRef with concrete before/after examples, plus a correctness/performance/maintainability iteration pass and a common-pitfalls section.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Claude skill that provides a structured, behavior-preserving workflow for migrating React class components to functional components using hooks, with emphasis on correctness pitfalls (deps, stale closures, cleanup) and iterative review passes.

Changes:

  • Introduces a new skill document with a pre-migration audit checklist and a step-by-step conversion workflow.
  • Adds a conversion map covering state, lifecycle methods, refs/instance fields, class methods, derived values, HOCs/context, and forwardRef/imperative handles.
  • Documents common hook migration pitfalls (stale closures, missing deps, identity churn, derived state, cleanup) and expected outputs/constraints.
Comments suppressed due to low confidence (3)

Claude/skills/class-to-functional-migration/SKILL.md:196

  • The guidance about dropping HOC wrappers is misleading: replacing an HOC (e.g., connect, withRouter) with hooks typically only requires changing the wrapped component itself; consumers that import/render the component usually do not need to be “rewritten as a hook”. Consider rephrasing to something like “drop the HOC wrapper once the component no longer relies on it, keeping the export shape the same to avoid breaking imports.”
Drop the HOC wrapper from the export once each consumer is rewritten as a hook.

Claude/skills/class-to-functional-migration/SKILL.md:280

  • In the stale-closure example, the note “or use the functional setter form” doesn’t apply because the interval callback is only reading count (logging), not updating state. Consider updating the guidance to an actually applicable fix (e.g., include count in deps, or store the latest value in a ref, or use a stable event callback pattern) so readers don’t apply an ineffective pattern.
// FIX: include count, or use the functional setter form
useEffect(() => {
  const id = setInterval(() => console.log(count), 1000);
  return () => clearInterval(id);
}, [count]);

Claude/skills/class-to-functional-migration/SKILL.md:213

  • The useImperativeHandle example omits the dependency array. For a migration guide that emphasizes stale-closure/identity issues, it would be clearer to show the third argument (e.g., [] for a stable handle, or deps when the handle uses reactive values) to avoid recreating the handle each render and to align with common linting expectations.
  useImperativeHandle(ref, () => ({
    focus: () => inputRef.current.focus(),
  }));

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

| `componentWillUnmount` | Cleanup function returned from `useEffect` |
| `getDerivedStateFromProps` | Compute during render, or sync via `useEffect` if needed |
| `shouldComponentUpdate` | Wrap export in `React.memo` with a custom comparator |
| `componentDidCatch` | Keep as a class `ErrorBoundary` — hooks cannot replace it|
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants