React 19 removes runtime propTypes checks for function components. Existing propTypes declarations on function components are ignored.
import PropTypes from "prop-types";
function Heading({ text }) {
return <h1>{text}</h1>;
}
Heading.propTypes = {
text: PropTypes.string,
};
interface HeadingProps {
text?: string;
}
function Heading({
text,
}: HeadingProps) {
return <h1>{text}</h1>;
}
Migration Remove function-component propTypes and migrate to TypeScript or another type-checking solution.
React 19 removes defaultProps support from function components. Class components continue to support defaultProps.
function Heading({
text,
}: {
text?: string;
}) {
return <h1>{text}</h1>;
}
Heading.defaultProps = {
text: "Hello",
};
function Heading({
text = "Hello",
}: {
text?: string;
}) {
return <h1>{text}</h1>;
}
Migration Replace function-component defaultProps with JavaScript default parameters.
React 19 removes the legacy contextTypes and getChildContext APIs that were deprecated in React 16.6.
class Parent extends React.Component {
getChildContext() {
return {
theme: "dark",
};
}
render() {
return <Child />;
}
}
Parent.childContextTypes = {
theme: PropTypes.string,
};
const ThemeContext =
React.createContext("light");
function Parent() {
return (
<ThemeContext value="dark">
<Child />
</ThemeContext>
);
}
Migration Replace contextTypes and getChildContext with createContext and the modern Context API.
React 19 removes string refs from class components. Ref callbacks or createRef should be used instead.
class Form extends React.Component {
componentDidMount() {
this.refs.input.focus();
}
render() {
return (
<input ref="input" />
);
}
}
class Form extends React.Component {
input = null;
componentDidMount() {
this.input?.focus();
}
render() {
return (
<input
ref={(input) => {
this.input = input;
}}
/>
);
}
}
Migration Replace string refs with callback refs or createRef. React provides a codemod for this migration.
React 19 removes support for the legacy module pattern factory component style.
function FactoryComponent() {
return {
render() {
return <div>Hello</div>;
},
};
}
function FactoryComponent() {
return <div>Hello</div>;
}
Migration Convert module pattern factories into normal function components.
React 19 removes React.createFactory, an API that predates widespread JSX adoption.
import {
createFactory,
} from "react";
const Button =
createFactory("button");
const element =
Button({
children: "Save",
});
const element = (
<button>
Save
</button>
);
Migration Replace React.createFactory usage with JSX.
React 19 removes the react-test-renderer/shallow entry point. React recommends moving away from shallow rendering.
import ShallowRenderer from
"react-test-renderer/shallow";
import ShallowRenderer from
"react-shallow-renderer";
Migration Prefer migrating tests to React Testing Library. If shallow rendering must temporarily remain, install react-shallow-renderer directly.
React 19 moves act to the React package. The react-dom/test-utils version is deprecated and the other legacy test utilities are removed.
import {
act,
} from "react-dom/test-utils";
import {
act,
} from "react";
Migration Import act directly from react. Review other react-dom/test-utils usage and migrate away from low-level test utilities.
React 19 removes ReactDOM.render after its deprecation in React 18. Applications must use createRoot.
import {
render,
} from "react-dom";
render(
<App />,
document.getElementById("root"),
);
import {
createRoot,
} from "react-dom/client";
const container =
document.getElementById("root");
const root =
createRoot(container!);
root.render(<App />);
Migration Replace ReactDOM.render with createRoot from react-dom/client. The React 19 migration recipe includes a codemod for this change.
React 19 removes the legacy ReactDOM.hydrate API. Server-rendered applications must use hydrateRoot.
import {
hydrate,
} from "react-dom";
hydrate(
<App />,
document.getElementById("root"),
);
import {
hydrateRoot,
} from "react-dom/client";
hydrateRoot(
document.getElementById("root")!,
<App />,
);
Migration Replace ReactDOM.hydrate with hydrateRoot from react-dom/client.
React 19 removes ReactDOM.unmountComponentAtNode. Applications using the root API should unmount through the root instance.
import {
unmountComponentAtNode,
} from "react-dom";
unmountComponentAtNode(
container,
);
const root =
createRoot(container);
root.render(<App />);
// Later:
root.unmount();
Migration Keep the root returned by createRoot and call root.unmount() when the application needs to be removed.
React 19 removes findDOMNode. The API was a legacy escape hatch that broke component abstraction and was fragile during refactoring.
import {
findDOMNode,
} from "react-dom";
useEffect(() => {
const input =
findDOMNode(component);
input?.focus();
}, []);
const inputRef =
useRef<HTMLInputElement>(null);
useEffect(() => {
inputRef.current?.focus();
}, []);
return (
<input ref={inputRef} />
);
Migration Replace findDOMNode with an explicit DOM ref.