migrate-class-to-hooks
Skill4 starsChanged 10 days agoMITView on GitHub
Convert React class components to function components with hooks one component at a time - characterization tests first, then map state to useState/useReducer, lifecycle methods to useEffect with correct dependencies and cleanup (or to event handlers and derived values where an effect isn't needed), refs to useRef, context to useContext, connect() to useSelector/useDispatch, keep error boundaries as classes, and verify behavior is unchanged. Use when asked to modernize class components or when touching a class component substantially in legacy/react-class-cra code.
In this repository32 other files it gives its agents.
- llms.txtllms.txt
- cve-checkSkill
- dependency-vetSkill
- git-commitSkill
- incident-supply-chainSkill
- migrate-angularjsSkill
- migrate-cordovaSkill
- migrate-cra-to-viteSkill
- migrate-dotnet-frameworkSkill
- migrate-ingress-nginxSkill
- migrate-strutsSkill
- migrate-vue2Skill
- migrate-xamarinSkill
- secrets-scanSkill
- security-auditSkill
- threat-model-liteSkill
- upgrade-angularSkill
- upgrade-djangoSkill
- upgrade-dotnetSkill
- upgrade-expressSkill
- upgrade-jquerySkill
- upgrade-laravelSkill
- upgrade-nestjsSkill
- upgrade-nextjsSkill
- upgrade-nodeSkill
- upgrade-nuxtSkill
- upgrade-phpSkill
- upgrade-pythonSkill
- upgrade-railsSkill
- upgrade-react-nativeSkill
- upgrade-spring-bootSkill
- upgrade-supabaseSkill
The file
We split this skill into the rules it gives an agent
6 rules. About 0 are common, 4 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 21
Read the component, its parents and tests.
- Distinctive: line 26
Characterization tests: if the component lacks tests, add Testing Library tests for its visible behavior (render output, user interactions, …
- Distinctive: line 55
Never convert without tests that pin current behavior.
- Very specific: line 56
Never silence the hooks lint rules or add // eslint-disable-next-line react-hooks/exhaustive-deps to make a conversion pass.
- Distinctive: line 57
Never convert error boundaries to function components.
- Distinctive: line 58
Never auto-commit, push or deploy.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Migrate class components → hooks
When to use
- The user asks to convert class components, or a class component needs substantial changes anyway.
- React is 16.8 or newer (hooks exist). Error boundaries stay classes (there's no hook equivalent).
Before you start
- Pick the scope with the user: one component (default), a feature folder, or leaf components first across the app. Never the whole app in one change.
- Read the component, its parents and tests. Note lifecycle methods,
setStatecallbacks, instance fields, refs, context (contextType,Consumer), HOCs (connect,withRouter) andgetDerivedStateFromProps. - Working tree clean; new branch.
Steps
- Characterization tests: if the component lacks tests, add Testing Library tests for its visible behavior (render output, user interactions, calls to props and APIs) and make them pass on the class version first.
- Convert the shell:
class X extends Component→function X(props)(or a typed arrow function per house style); destructure props; movedefaultPropsto default parameter values. - State: each independent
this.statefield →useState; related fields or complex transitions →useReducer. Replacethis.setState(prev => …)with functional updates.setState(…, callback)→ do the follow-up in the event handler or an effect keyed on that state. - Lifecycle:
- work that responds to a user action → the event handler, not an effect;
- derived data → compute during render (
useMemoonly if measured slow, or let React Compiler handle it); - subscriptions, timers, DOM integrations:
componentDidMount+componentWillUnmount→ oneuseEffectwith cleanup; componentDidUpdate(prevProps)comparisons →useEffectwith those values as dependencies;getDerivedStateFromProps→ derive during render, or reset state with akeyon the component;shouldComponentUpdate/PureComponent→memo()only if needed. Include every value the effect uses in its dependency array; don't silencereact-hooks/exhaustive-deps.
- Instance fields and refs: mutable instance fields (
this.timer) →useRef;createRef→useRef; callback refs stay callback refs;forwardRefonly on React < 19 (19 passesrefas a prop). - Context and HOCs:
static contextType/Consumer→useContext;connect(mapState, mapDispatch)→useSelector/useDispatch(keep selectors memoized);withRouter→ the router's hooks (useNavigate,useParams). - Run the tests, fix differences, and check effects don't run twice incorrectly under
StrictMode(cleanup must undo setup). - Verify (next section); show the diff and results; commit only when asked (
git-commitskill).
Verify
npx tsc --noEmit # TypeScript projects
npx eslint <changed files> # with eslint-plugin-react-hooks
npm test -- <component test files> # or: npx vitest run <files>
npm run buildThen exercise the component in the app with the console open: same output, no extra requests on re-render, no warnings about missing dependencies or updates on unmounted components, subscriptions cleaned up when navigating away.
Safety
- Never convert without tests that pin current behavior; never change behavior and structure in the same commit.
- Never silence the hooks lint rules or add
// eslint-disable-next-line react-hooks/exhaustive-depsto make a conversion pass. - Never convert error boundaries to function components.
- Never auto-commit, push or deploy.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

