}>,
+) => {
+ if (reactMajor >= 19) {
+ const Component = (props: any) => render(props, props.ref ?? null);
+ Component.displayName = render.displayName ?? render.name;
+ return Component as React.ForwardRefExoticComponent;
+ }
+ return React.forwardRef(
+ render as React.ForwardRefRenderFunction>,
+ );
+};
+```
+
+The shim provides two key benefits:
+
+1. Type safety - TypeScript will warn if props are spread incorrectly
+2. Forward compatibility - Components using the shim will work correctly in all supported React versions
+
+This is how we implemented it:
+
+```tsx
+// Before
+const GridRoot = React.forwardRef((props, ref) => {
+ const state = useGridState();
+ return ;
+});
+
+// After
+const GridRoot = forwardRef((props, ref) => {
+ const state = useGridState();
+ return ;
+});
+```
+
+## Phase 2: Moving to React 19
+
+After ensuring compatibility, we started working on migrating the codebase to React 19. This involved:
+
+1. Updating all package dependencies to their React 19-compatible versions (including docs website migration to Next.js 15)
+2. Migrating test utilities to work with React 19
+3. Ensuring all components work with the new React 19 features
+4. Updating CI to run tests with React 18
+5. Updating type references with `RefObject` for React 19 and `MutableRefObject` for earlier versions
+
+The biggest change in this phase was around the [`useRef()` hook update](https://react.dev/blog/2024/04/25/react-19-upgrade-guide#useref-requires-argument).
+The `apiRef` in the Data Grid component had to be updated from `MutableRefObject` to `RefObject` for React 19 only, to avoid type errors for users who haven't migrated yet.
+
+### Our own `RefObject`
+
+To provide different types for `apiRef` in the Data Grid component for different React versions, we created our own `RefObject` type.
+
+We leveraged the fact that `useRef()` requires a param in React 19 to ensure `RefObject` would be evaluated as `MutableRefObject` for React < 19, and as `RefObject` otherwise.
+
+```ts
+// in React 19 useRef requires a parameter, so `() => any` will not match anymore
+export type RefObject = typeof React.useRef extends () => any
+ ? React.MutableRefObject
+ : React.RefObject;
+```
+
+## Conclusion
+
+The migration to React 19 was a significant undertaking.
+By breaking it down into two phases we were able to quickly provide React 19 compatibility for our users while we worked on our own migration.
+
+The utilities and refactoring made during the migration will make it easier to maintain backward compatibility in the future, since `forwardRef` updates and `apiRef` type changes can all be done from one place.
+
+Though this project was spearheaded by the MUI X team, we owe a special thanks to our colleagues who maintain Material UI for their massive help in adding React 19 support to both v5 and v6 of `@mui/material`.
+They also provided the necessary updates to the internal tools that both of our repositories use for building and testing our components.
+
+We hope our experience can be useful and shorten the time needed for your own React 19 migration!
diff --git a/docs/src/modules/components/TopLayoutBlog.js b/docs/src/modules/components/TopLayoutBlog.js
index dfac84a70564ea..ebca6118450a53 100644
--- a/docs/src/modules/components/TopLayoutBlog.js
+++ b/docs/src/modules/components/TopLayoutBlog.js
@@ -141,6 +141,11 @@ export const authors = {
avatar: 'https://avatars.githubusercontent.com/u/1423607',
github: 'romgrk',
},
+ arminmeh: {
+ name: 'Armin Mehinović',
+ avatar: 'https://avatars.githubusercontent.com/u/4390250',
+ github: 'arminmeh',
+ },
};
const classes = {