
React19 Source Patterns
- 872 installs
- 37.1k repo stars
- Updated July 28, 2026
- github/awesome-copilot
Reference for React 19 source-file migration patterns, including API changes, ref handling, and context updates.
About
Reference for React 19 source-file migration patterns, including API changes, ref handling, and context updates. Reference for every source-file migration required for React 19. The react19-source-patterns skill documents workflows, constraints, and examples from SKILL.md for agent-assisted execution.
- # React 19 Source Migration Patterns
- Reference for every source-file migration required for React 19.
- | Pattern | Action | Reference |
- | `ReactDOM.render(...)` | → `createRoot().render()` | See references/api-migrations.md |
- | `ReactDOM.hydrate(...)` | → `hydrateRoot(...)` | See references/api-migrations.md |
React19 Source Patterns by the numbers
- 872 all-time installs (skills.sh)
- +21 installs in the week ending Jul 28, 2026 (Skillselion tracking)
- Ranked #192 of 1,453 DevOps & CI/CD skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Jul 28, 2026 (Skillselion catalog sync)
react19-source-patterns capabilities & compatibility
- Capabilities
- # react 19 source migration patterns · reference for every source file migration requir · | pattern | action | reference | · | `reactdom.render(...)` | → `createroot().rende
- Use cases
- documentation
What react19-source-patterns says it does
Reference for React 19 source-file migration patterns, including API changes, ref handling, and context updates.
npx skills add https://github.com/github/awesome-copilot --skill react19-source-patternsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 872 |
|---|---|
| repo stars | ★ 37.1k |
| Security audit | 3 / 3 scanners passed |
| Last updated | July 28, 2026 |
| Repository | github/awesome-copilot ↗ |
How do I apply react19-source-patterns using the workflow in its SKILL.md?
Reference for React 19 source-file migration patterns, including API changes, ref handling, and context updates.
Who is it for?
Developers following the react19-source-patterns skill for the tasks it documents.
Skip if: Tasks outside the react19-source-patterns scope described in SKILL.md.
When should I use this skill?
User mentions react19-source-patterns or related triggers from the skill description.
What you get
Working react19-source-patterns setup aligned with the documented patterns and constraints.
- React 19 migration patches
- Updated root entry files
- Removed-API replacement snippets
Files
React 19 Source Migration Patterns
Reference for every source-file migration required for React 19.
Quick Reference Table
| Pattern | Action | Reference |
|---|---|---|
ReactDOM.render(...) | → createRoot().render() | See references/api-migrations.md |
ReactDOM.hydrate(...) | → hydrateRoot(...) | See references/api-migrations.md |
unmountComponentAtNode | → root.unmount() | Inline fix |
ReactDOM.findDOMNode | → direct ref | Inline fix |
forwardRef(...) wrapper | → ref as direct prop | See references/api-migrations.md |
Component.defaultProps = {} | → ES6 default params | See references/api-migrations.md |
useRef() no arg | → useRef(null) | Inline fix add null |
| Legacy Context | → createContext | → api-migrations.md#legacy-context |
String refs this.refs.x | → createRef() | → api-migrations.md#string-refs |
import React from 'react' (unused) | Remove | Only if no React. usage in file |
PropTypes Rule
Do not remove .propTypes assignments. The prop-types package still works as a standalone validator. React 19 only removes the built-in runtime checking from the React package the package itself remains valid.
Add this comment above any .propTypes block:
// NOTE: React 19 no longer runs propTypes validation at runtime.
// PropTypes kept for documentation and IDE tooling only.Read the Reference
For full before/after code for each migration, read `references/api-migrations.md`. It contains the complete patterns including edge cases for forwardRef with useImperativeHandle, defaultProps null vs undefined behavior, and legacy context provider/consumer cross-file migrations.
React 19 API Migrations Reference
Complete before/after patterns for all React 19 breaking changes and removed APIs.
---
ReactDOM Root API Migration
React 19 requires createRoot() or hydrateRoot() for all apps. If the React 18 migration already ran, this is done. Verify it's correct.
Pattern 1: createRoot() CSR App
// Before (React 18 or earlier):
import ReactDOM from 'react-dom';
ReactDOM.render(<App />, document.getElementById('root'));
// After (React 19):
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'));
root.render(<App />);Pattern 2: hydrateRoot() SSR/Static App
// Before (React 18 server-rendered app):
import ReactDOM from 'react-dom';
ReactDOM.hydrate(<App />, document.getElementById('root'));
// After (React 19):
import { hydrateRoot } from 'react-dom/client';
hydrateRoot(document.getElementById('root'), <App />);Pattern 3: unmountComponentAtNode() Removed
// Before (React 18):
import ReactDOM from 'react-dom';
ReactDOM.unmountComponentAtNode(container);
// After (React 19):
const root = createRoot(container); // Save the root reference
// later:
root.unmount();Caveat: If the root reference was never saved, you must refactor to pass it around or use a global registry.
---
findDOMNode() Removed
Pattern 1: Direct ref
// Before (React 18):
import { findDOMNode } from 'react-dom';
const domNode = findDOMNode(componentRef);
// After (React 19):
const domNode = componentRef.current; // refs point directly to DOMPattern 2: Class Component ref
// Before (React 18):
import { findDOMNode } from 'react-dom';
class MyComponent extends React.Component {
render() {
return <div ref={ref => this.node = ref}>Content</div>;
}
getWidth() {
return findDOMNode(this).offsetWidth;
}
}
// After (React 19):
// Note: findDOMNode() is removed in React 19. Eliminate the call entirely
// and use direct refs to access DOM nodes instead.
class MyComponent extends React.Component {
nodeRef = React.createRef();
render() {
return <div ref={this.nodeRef}>Content</div>;
}
getWidth() {
return this.nodeRef.current.offsetWidth;
}
}---
forwardRef() - Optional Modernization
Pattern 1: Function Component Direct ref
// Before (React 18):
import { forwardRef } from 'react';
const Input = forwardRef((props, ref) => (
<input ref={ref} {...props} />
));
function App() {
const inputRef = useRef(null);
return <Input ref={inputRef} />;
}
// After (React 19):
// Simply accept ref as a regular prop:
function Input({ ref, ...props }) {
return <input ref={ref} {...props} />;
}
function App() {
const inputRef = useRef(null);
return <Input ref={inputRef} />;
}Pattern 2: forwardRef + useImperativeHandle
// Before (React 18):
import { forwardRef, useImperativeHandle } from 'react';
const TextInput = forwardRef((props, ref) => {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => inputRef.current.focus(),
clear: () => { inputRef.current.value = ''; }
}));
return <input ref={inputRef} {...props} />;
});
function App() {
const textRef = useRef(null);
return (
<>
<TextInput ref={textRef} />
<button onClick={() => textRef.current.focus()}>Focus</button>
</>
);
}
// After (React 19):
function TextInput({ ref, ...props }) {
const inputRef = useRef(null);
useImperativeHandle(ref, () => ({
focus: () => inputRef.current.focus(),
clear: () => { inputRef.current.value = ''; }
}));
return <input ref={inputRef} {...props} />;
}
function App() {
const textRef = useRef(null);
return (
<>
<TextInput ref={textRef} />
<button onClick={() => textRef.current.focus()}>Focus</button>
</>
);
}Note: useImperativeHandle is still valid; only the forwardRef wrapper is removed.
---
defaultProps Removed
Pattern 1: Function Component with defaultProps
// Before (React 18):
function Button({ label = 'Click', disabled = false }) {
return <button disabled={disabled}>{label}</button>;
}
// WORKS BUT is removed in React 19:
Button.defaultProps = {
label: 'Click',
disabled: false
};
// After (React 19):
// ES6 default params are now the ONLY way:
function Button({ label = 'Click', disabled = false }) {
return <button disabled={disabled}>{label}</button>;
}
// Remove all defaultProps assignmentsPattern 2: Class Component defaultProps
// Before (React 18):
class Button extends React.Component {
static defaultProps = {
label: 'Click',
disabled: false
};
render() {
return <button disabled={this.props.disabled}>{this.props.label}</button>;
}
}
// After (React 19):
// Use default params in constructor or class field:
class Button extends React.Component {
constructor(props) {
super(props);
this.label = props.label || 'Click';
this.disabled = props.disabled || false;
}
render() {
return <button disabled={this.disabled}>{this.label}</button>;
}
}
// Or simplify to function component with ES6 defaults:
function Button({ label = 'Click', disabled = false }) {
return <button disabled={disabled}>{label}</button>;
}Pattern 3: defaultProps with null
// Before (React 18):
function Component({ value }) {
// defaultProps can set null to reset a parent-passed value
return <div>{value}</div>;
}
Component.defaultProps = {
value: null
};
// After (React 19):
// Use explicit null checks or nullish coalescing:
function Component({ value = null }) {
return <div>{value}</div>;
}
// Or:
function Component({ value }) {
return <div>{value ?? null}</div>;
}---
useRef Without Initial Value
Pattern 1: useRef()
// Before (React 18):
const ref = useRef(); // undefined initially
// After (React 19):
// Explicitly pass null as initial value:
const ref = useRef(null);
// Then use current:
ref.current = someElement; // Set it manually laterPattern 2: useRef with DOM Elements
// Before:
function Component() {
const inputRef = useRef();
return <input ref={inputRef} />;
}
// After:
function Component() {
const inputRef = useRef(null); // Explicit null
return <input ref={inputRef} />;
}---
Legacy Context API Removed
Pattern 1: React.createContext vs contextTypes
// Before (React 18 not recommended but worked):
// Using contextTypes (old PropTypes-style context):
class MyComponent extends React.Component {
static contextTypes = {
theme: PropTypes.string
};
render() {
return <div style={{ color: this.context.theme }}>Text</div>;
}
}
// Provider using getChildContext (old API):
class App extends React.Component {
static childContextTypes = {
theme: PropTypes.string
};
getChildContext() {
return { theme: 'dark' };
}
render() {
return <MyComponent />;
}
}
// After (React 19):
// Use createContext (modern API):
const ThemeContext = React.createContext(null);
function MyComponent() {
const theme = useContext(ThemeContext);
return <div style={{ color: theme }}>Text</div>;
}
function App() {
return (
<ThemeContext.Provider value="dark">
<MyComponent />
</ThemeContext.Provider>
);
}Pattern 2: Class Component Consuming createContext
// Before (class component consuming old context):
class MyComponent extends React.Component {
static contextType = ThemeContext;
render() {
return <div style={{ color: this.context }}>Text</div>;
}
}
// After (still works in React 19):
// No change needed for static contextType
// Continue using this.contextImportant: If you're still using the old contextTypes + getChildContext pattern (not modern createContext), you must migrate to createContext the old pattern is completely removed.
---
String Refs Removed
Pattern 1: this.refs String Refs
// Before (React 18):
class Component extends React.Component {
render() {
return (
<>
<input ref="inputRef" />
<button onClick={() => this.refs.inputRef.focus()}>Focus</button>
</>
);
}
}
// After (React 19):
class Component extends React.Component {
inputRef = React.createRef();
render() {
return (
<>
<input ref={this.inputRef} />
<button onClick={() => this.inputRef.current.focus()}>Focus</button>
</>
);
}
}Pattern 2: Callback Refs (Recommended)
// Before (React 18):
class Component extends React.Component {
render() {
return (
<>
<input ref="inputRef" />
<button onClick={() => this.refs.inputRef.focus()}>Focus</button>
</>
);
}
}
// After (React 19 callback is more flexible):
class Component extends React.Component {
constructor(props) {
super(props);
this.inputRef = null;
}
render() {
return (
<>
<input ref={(el) => { this.inputRef = el; }} />
<button onClick={() => this.inputRef?.focus()}>Focus</button>
</>
);
}
}---
Unused React Import Removal
Pattern 1: React Import After JSX Transform
// Before (React 18):
import React from 'react'; // Needed for JSX transform
function Component() {
return <div>Text</div>;
}
// After (React 19 with new JSX transform):
// Remove the React import if it's not used:
function Component() {
return <div>Text</div>;
}
// BUT keep it if you use React.* APIs:
import React from 'react';
function Component() {
return <div>{React.useState ? 'yes' : 'no'}</div>;
}Scan for Unused React Imports
# Find imports that can be removed:
grep -rn "^import React from 'react';" src/ --include="*.js" --include="*.jsx"
# Then check if the file uses React.*, useContext, etc.---
Complete Migration Checklist
# 1. Find all ReactDOM.render calls:
grep -rn "ReactDOM.render" src/ --include="*.js" --include="*.jsx"
# Should be converted to createRoot
# 2. Find all ReactDOM.hydrate calls:
grep -rn "ReactDOM.hydrate" src/ --include="*.js" --include="*.jsx"
# Should be converted to hydrateRoot
# 3. Find all forwardRef usages:
grep -rn "forwardRef" src/ --include="*.js" --include="*.jsx"
# Check each one to see if it can be removed (most can)
# 4. Find all .defaultProps assignments:
grep -rn "\.defaultProps\s*=" src/ --include="*.js" --include="*.jsx"
# Replace with ES6 default params
# 5. Find all useRef() without initial value:
grep -rn "useRef()" src/ --include="*.js" --include="*.jsx"
# Add null: useRef(null)
# 6. Find old context (contextTypes):
grep -rn "contextTypes\|childContextTypes\|getChildContext" src/ --include="*.js" --include="*.jsx"
# Migrate to createContext
# 7. Find string refs (ref="name"):
grep -rn 'ref="' src/ --include="*.js" --include="*.jsx"
# Migrate to createRef or callback ref
# 8. Find unused React imports:
grep -rn "^import React from 'react';" src/ --include="*.js" --include="*.jsx"
# Check if React is used in the fileRelated skills
How it compares
Pick react19-source-patterns for React 19 API replacement snippets; use framework-specific upgrade guides when migrating Next.js or Remix routing layers beyond core React APIs.
FAQ
What does react19-source-patterns do?
Reference for React 19 source-file migration patterns, including API changes, ref handling, and context updates.
When should I use react19-source-patterns?
Invoke when Reference for React 19 source-file migration patterns, including API changes, ref handling, and context updates.
Is react19-source-patterns safe to install?
Review the Security Audits panel on this page before installing in production.