Testing
react-*JSSG codemods against the relevant legacy orcommonsbaselines on real-world open-source repos.
We searched public GitHub repos for the exact code patterns our tracked React codemods target. Below are the recommended test repos, organized by codemod, with match counts and React version context.
Key finding: useFormState from react-dom has zero real-world adoption. No open-source repo imports useFormState from react-dom. The API was renamed to useActionState before it saw meaningful use.
Additional modern spot-check: As of 2026-04-17, calcom/cal.com redirects to calcom/cal.diy. It is a useful React 18/19 TypeScript monorepo target for validating use-context-hook and replace-act-import on current code.
Phase 2 import note: On 2026-04-20, 14 additional JSSG codemods were brought forward from align-with-legacy-codemods. These codemods target older or niche migration surfaces, so their immediate validation strategy is fixture-first rather than open-source repo-first. Only class remains legacy-only.
Recipe alignment note (2026-04-23): The React 19 migration recipe is now aligned with codemod/commons and uses prop-types-typescript instead of react-proptypes-to-prop-types. This plan tracks both codemods for now because the older React.PropTypes transform still exists in this repo, but the new recipe-critical step is the inline propTypes -> TypeScript migration.
prop-types-typescript reevaluation note (2026-04-23): The first side-by-side pass against codemod/commons is complete. On the sampled real-repo surface, JSSG now has zero commons-only files, zero sampled parse failures, and 12 valid JSSG-only MetaMask rewrites because commons crashes on those files. salesforce/design-system-react, MetaMask/metamask-extension, and atlassian/react-beautiful-dnd remain the right comparison repos for ongoing regression checks.
Coverage audit (2026-04-21): Current upstream reactjs/react-codemod HEAD is 5207d594fad6f8b39c51fd7edd2bcb51047dc872. Its transforms/ directory contains 21 transforms. This repo now has JSSG implementations for 20 of them; the only upstream transform without a JSSG counterpart here is class.
Additional rollout research (2026-04-21): A second repo sweep found three especially useful follow-on candidates beyond the original four test repos:
salesforce/design-system-reactat825de01(React 17) remains a high-value second source forreplace-reactdom-render,replace-act-import, anduse-context-hook.MetaMask/metamask-extensionat9c3b57c(React 17) is a strongreplace-act-importvalidation target with 18 real test-file imports.react-native-snap-carouselat9c39995givesreact-native-view-prop-typesan exact real-world source surface across 4 files, including the tricky case whereViewPropTypesis already imported.DataTurksat039d57egiveserror-boundariesan exactunstable_handleErrorsource hit in production code.airbnb/react-datesatb7bad38is a useful class-heavy repo for generic class codemods such aspure-componentandsort-comp, though it does not expose many exact legacy API hits.rsuiteat0b1482dstill has a large rawReactDOM.rendercount, but current HEAD is heavily docs/example-driven, so it is a lower-quality source thansalesforce/design-system-reactfor rollout decisions.
| Repo | Stars | React Version | Patterns Found | Language |
|---|---|---|---|---|
| youzan/zent | 2.2k | 17.0.x (dev), ^17 (peer) | ReactDOM.render (~398), react-dom/test-utils (~17), useContext |
TypeScript 65% |
| salesforce/design-system-react | ~1k | ^17.0.2 (dev), >=16.8 (peer) | ReactDOM.render (~315 grep matches / ~316 files under components/), useContext |
JavaScript |
| atlassian/react-beautiful-dnd | 33k | 16.13.1 (dev), ^16.8.5‖^17‖^18 (peer) | react-dom/test-utils (multiple), ReactDOM.render |
JS + Flow |
calcom/cal.com (redirects to calcom/cal.diy) |
41.4k | 18.2.0 in apps/web, `^18 |
^19` across workspace packages |
| Repo | React Version | Primary Pattern | Grep matches |
|---|---|---|---|
| MetaMask/metamask-extension | 13.1k stars, React ^16.12.0 | react-dom/test-utils |
~18 |
| rsuite/rsuite | React ^19.0.0 (dev), >=18 (peer) | ReactDOM.render |
~776 |
| OnsenUI/OnsenUI (react-onsenui) | React ^18 (peer) | react-dom/test-utils |
~37 |
| Repo | React Version | Patterns Found | Notes |
|---|---|---|---|
| nylas/nylas-mail | 24.8k stars, React ~15.x (Electron) | React.PropTypes (~193), this.refs. (~41) |
Archived 2017, JS + CoffeeScript |
| azat-co/react-quickly | React ~15.x | React.PropTypes (~155), this.refs. (~120) |
Book examples, highest string ref count |
| cockpit-project/cockpit | 11k stars, varies | this.refs. (~54) |
Active project, Linux admin tool |
Pattern: ReactDOM.render(element, container) → createRoot(container).render(element)
| Repo | Grep matches | Notes |
|---|---|---|
| rsuite/rsuite | ~776 | Largest count, but already on React 19 dev |
| alibaba-fusion/next | ~657 | Alibaba component library |
| kingdee/kdesign | ~482 | React component design system |
| youzan/zent | ~398 | ★ React 17, TypeScript, ideal target |
| salesforce/design-system-react | ~315 | ★ React 17, enterprise library (~316 real JS/JSX files under components/ on rollout inspection) |
| nfl/react-helmet | ~100+ | Widely used, small scope |
Recommended test repo: youzan/zent (React 17 + TypeScript + high match count)
Legacy counterpart: npx react-codemod react/19/replace-reactdom-render
Pattern: import { act } from 'react-dom/test-utils' → import { act } from 'react'
| Repo | Grep matches | Notes |
|---|---|---|
| OnsenUI/OnsenUI | ~37 | ★ Highest count |
| Foundry376/Mailspring | ~23 | Electron email client |
| MetaMask/metamask-extension | ~18 | ★ Very well-known, React 16 |
| youzan/zent | ~17 | Also has ReactDOM.render |
| atlassian/react-beautiful-dnd | multiple | Popular DnD library |
| calcom/cal.com | 1 | Modern React 18/19 monorepo, verified on tag v6.2.0 |
Recommended test repos: MetaMask/metamask-extension (brand recognition) + OnsenUI/OnsenUI (highest count) + calcom/cal.com (modern React 18/19 spot-check)
Legacy counterpart: npx react-codemod react/19/replace-act-import
Pattern: React.PropTypes.xxx → import PropTypes from 'prop-types'; PropTypes.xxx
| Repo | Grep matches | Notes |
|---|---|---|
| jianliaoim/talk-os | ~253 | CoffeeScript + React, older |
| nylas/nylas-mail | ~193 | ★ Archived, also has string refs |
| azat-co/react-quickly | ~155 | ★ Book examples, also has string refs |
| yhat/rodeo | ~125 | Data science IDE, older |
Note: This pattern only exists in React ≤15.x codebases. All recommended repos are older/archived. This is expected — React.PropTypes was removed in React 16.
Recommended test repo: nylas/nylas-mail (well-known + has 2 patterns)
Legacy counterpart: npx react-codemod React-PropTypes-to-prop-types
Pattern: Component.propTypes = { ... } / static propTypes = { ... } → generated Props interface + component type annotation, with converted propTypes removed or preserved based on options.
Because this codemod targets inline propTypes object declarations rather than a unique import token, the best repo selection came from the current React 19 assessment corpus instead of grep.app-wide counts.
| Repo | Matched files | Notes |
|---|---|---|
| salesforce/design-system-react | 98 | ★ Strong JS/class-component surface; same repo also stress-tests replace-reactdom-render and use-context-hook |
| MetaMask/metamask-extension | 275 | ★ Largest real surface in the current corpus; mixed JS component patterns |
| atlassian/react-beautiful-dnd | 2 | Small but clean overlap/parity spot-check |
| youzan/zent | 0 | No inline propTypes = {} surface in current slice |
| calcom/cal.diy | 0 | No inline propTypes = {} surface in current slice |
Recommended test repos: salesforce/design-system-react + MetaMask/metamask-extension + atlassian/react-beautiful-dnd
Comparison baseline: codemod/commons/codemods/react/prop-types-typescript
Current status: Initial parity work is complete and the sampled real-repo verdict is now "JSSG ahead". design-system-react is effectively at functional parity aside from one non-functional CSS indentation drift and one commons crash; MetaMask is a stress case where JSSG covers 12 additional real files because commons crashes; react-beautiful-dnd is a clean 2/2 parity spot-check.
Pattern: ref="myRef" in JSX inside class components → ref={(ref) => { this.myRef = ref; }}
| Repo | Grep matches | Notes |
|---|---|---|
| azat-co/react-quickly | ~120 | ★ Highest count, also has PropTypes |
| cockpit-project/cockpit | ~54 | Active Linux admin tool |
| nicehash/whistle | ~52 | Network debugging tool |
| bitshares/bitshares-ui | ~43 | Crypto exchange UI |
| nylas/nylas-mail | ~41 | Also has PropTypes |
| BoostIO/BoostNote-Legacy | many | Note-taking app |
| atom/atom | ~36 | Archived text editor |
Note: Like PropTypes, string refs only exist in older codebases (React ≤15.x, deprecated from 16).
Recommended test repo: azat-co/react-quickly (highest count + PropTypes combo)
Legacy counterpart: npx react-codemod react/19/replace-string-ref
Pattern: useContext(SomeContext) / React.useContext(SomeContext) → use(SomeContext)
This pattern is ubiquitous — virtually every React application uses useContext. Any of the Tier 1 repos will work.
Additional verified modern repo: calcom/cal.com (redirects to calcom/cal.diy) at tag v6.2.0 yields 30 transformable files with the current local workflow.
Recommended test repos: youzan/zent + salesforce/design-system-react + calcom/cal.com (modern React 18/19 monorepo)
Legacy counterpart: npx react-codemod react/19/use-context-hook
Pattern: import { useFormState } from 'react-dom' → import { useActionState } from 'react'
Searched grep.app for useFormState combined with react-dom across all languages. Zero matches. The only useFormState in the wild comes from react-hook-form (completely different API).
This API was renamed to useActionState before it saw meaningful public adoption. Testing should rely on synthetic fixtures only (which are already in our test suite).
| Repo | render | act-import | React.PropTypes | prop-types-typescript | string-ref | useContext | useFormState |
|---|---|---|---|---|---|---|---|
| youzan/zent | ✅ ~398 | ✅ ~17 | — | — | — | ✅ | — |
| salesforce/design-system-react | ✅ ~315 | — | — | ✅ 98 matched | — | ✅ | — |
calcom/cal.com (v6.2.0) |
— | ✅ 1 | — | — | — | ✅ 30 transformable files | — |
| MetaMask/metamask-extension | — | ✅ ~18 | — | ✅ 275 matched | — | ✅ | — |
| atlassian/react-beautiful-dnd | ✅ | ✅ multiple | — | ✅ 2 matched | — | — | — |
| nylas/nylas-mail | — | — | ✅ ~193 | — | ✅ ~41 | — | — |
| azat-co/react-quickly | — | — | ✅ ~155 | — | ✅ ~120 | — | — |
| (synthetic fixtures) | — | — | — | — | — | — | ✅ |
Minimum repos to cover all 6 viable codemods: 3 (salesforce/design-system-react + MetaMask/metamask-extension + azat-co/react-quickly)
For modern React 18/19 coverage, calcom/cal.com is a strong fourth repo even though it is not required for minimum pattern coverage.
The codemods below were imported into the current branch from align-with-legacy-codemods on 2026-04-20. Because many of them target legacy code patterns that are harder to find reliably in modern public repos, the first evaluation pass should rely on their curated fixture suites, differential tests, and targeted error/warning tests.
The Next Real-Repo Priority column reflects pre-sampling planning intent. Rows whose real-repo pass has since been completed in TESTING_REPORT.md are marked Sampled with a one-line outcome — those rows no longer need further real-repo work to unblock parity decisions.
| Codemod | Initial Evaluation Surface | Next Real-Repo Priority |
|---|---|---|
create-element-to-jsx |
34 fixtures + error/differential tests | Sampled (parity on react-quickly) |
error-boundaries |
2 fixtures | Sampled (parity on DataTurks) |
find-dom-node |
9 fixtures | High |
manual-bind-to-arrow |
12 fixtures | Sampled (parity on react-quickly after fix) |
pure-component |
11 fixtures + warning/differential tests | High |
pure-render-mixin |
7 fixtures | Medium |
react-dom-to-react-dom-factories |
11 fixtures | Sampled (parity on react-quickly after fix) |
react-native-view-prop-types |
12 fixtures | Sampled (JSSG safer on react-native-snap-carousel) |
react-to-react-dom |
14 fixtures + error tests | High |
remove-context-provider |
7 fixtures | Sampled (parity on calcom/cal.diy) |
remove-forward-ref |
18 fixtures | Sampled (JSSG ahead on calcom/cal.diy after fix) |
rename-unsafe-lifecycles |
9 fixtures | Sampled (parity on nylas-mail) |
sort-comp |
11 fixtures | Medium |
update-react-imports |
33 fixtures | Sampled, inconclusive (legacy parser failure on youzan/zent; cleaner comparison target still needed) |
For these imported codemods, the recommended evaluation order is:
- Keep fixture suites green in this repo.
- Run targeted side-by-side repo sampling for the highest-priority packages.
- Promote individual codemods from fixture-verified to replacement-grade only after real-repo parity is demonstrated.
Real-repo candidate matches already found in the current testing repos:
| Codemod | Repo Candidate | Notes |
|---|---|---|
create-element-to-jsx |
react-quickly |
Real React.createElement(...) source files in chapter examples |
manual-bind-to-arrow |
react-quickly |
Constructor .bind(this) patterns in JSX source files |
find-dom-node |
react-quickly |
Sparse source hits in spare-parts examples; many other matches are library internals |
react-dom-to-react-dom-factories |
react-quickly |
Legacy React.DOM.* example app under bundled React examples |
rename-unsafe-lifecycles |
nylas-mail |
Strong real-world usage across app source and internal packages |
remove-forward-ref |
calcom/cal.diy |
Modern forwardRef(...) usage in app and UI packages |
remove-context-provider |
calcom/cal.diy |
Many Context.Provider wrappers in source packages |
update-react-imports |
youzan/zent, calcom/cal.diy |
Broad modern React import surface, especially in TS/TSX |
Additional real-repo candidate matches confirmed on 2026-04-21:
| Codemod | Repo Candidate | Notes |
|---|---|---|
error-boundaries |
DataTurks |
Exact unstable_handleError hit in bazaar/src/components/ErrorBoundary/ErrorBoundary.js |
react-native-view-prop-types |
react-native-snap-carousel |
Exact View.propTypes source hits in 4 files; includes existing ViewPropTypes import edge case |
pure-component |
airbnb/react-dates |
21 class-component files on current HEAD, mostly wrappers/examples and a few library classes |
sort-comp |
airbnb/react-dates, salesforce/design-system-react |
Good class-heavy surfaces for behavior comparison, even though the pattern itself is structural rather than API-specific |
replace-reactdom-render |
salesforce/design-system-react |
316 real JS/JSX files under components/, much stronger than docs-heavy rsuite HEAD for rollout decisions |
replace-act-import |
MetaMask/metamask-extension |
18 exact imports under ui/ tests |
- Clone the repo at a recent tagged release
- Run the JSSG codemod (
react-<name>orreact-19-<name>):npx codemod@latest <codemod-name> --target <path>
- Capture the diff →
results/jssg/<codemod>/<repo>.diff - Reset the repo (
git checkout .) - Run the legacy jscodeshift codemod (from
reactjs/react-codemod):npx react-codemod <codemod-name> <path>
- Capture the diff →
results/legacy/<codemod>/<repo>.diff - Compare the two diffs:
- Files transformed (count + list)
- Transformation correctness
- Edge cases handled differently
- Performance (execution time)
- Document findings per codemod
- Coverage: How many files / instances were transformed
- Correctness: Do both produce valid, equivalent code
- Edge cases: Where do they diverge
- Performance: Wall-clock execution time
- Errors: Any crashes or partial transformations
- Match counts in the per-codemod tables above are raw grep.app hits — not file counts. They are approximate and may include comments, docs, or multiple occurrences in the same file. The authoritative files transformed numbers live in
TESTING_REPORT.md, where they are consistently smaller than the raw match counts reported here. - Some repos are archived/unmaintained — that's fine for testing, the code patterns are what matter
useFormStatetesting is synthetic-only; recommend documenting this proactively for the React teamuseContextis so widespread that any React 16.8+ repo works; no need for a dedicated test repocalcom/cal.comredirected tocalcom/cal.diyon GitHub by 2026-04-17; keep both names in documentation for discoverability- Imported codemods from
align-with-legacy-codemodsshould be evaluated fixture-first in this branch before expanding to repo-based parity work