apps/public-docsite-v9/src/Concepts/ReactVersionSupport.mdx
import { Meta } from '@storybook/addon-docs/blocks';
<Meta title="Concepts/Developer/React Version Support" />ℹ️ Note: Our migration docs focus solely on FluentUI related changes.
If you're migrating between React major versions, please refer to the official React documentation for comprehensive migration guides.
For migrating your codebase TypeScript types, you can leverage Types React Codemod
Full support starting @fluentui/react-components v9.0.0.
Full support starting @fluentui/react-components v9.66.0.
💡 Check Following PR for further details https://github.com/microsoft/fluentui/pull/34456
NONE
Because @types/react@18 Breaking Changes, we needed to loosen Slot children property to any.
This change will affect users that use Slot children as a function in conjunction with TypeScript strict mode.
If that's your case, TypeScript will fail on noImplicitAny. To mitigate this you need to add type assertions (satisfies SlotRenderFunction<T>)
Before:
import * as React from 'React';
<Button
// children was inferred as union of ReactNode and SlotRenderFunction
icon={{ children: (Component, props) => <Component {...props /> }}
>
Label
</Button>
After:
import * as React from 'React';
import { type SlotRenderFunction } from '@fluentui/react-utilities';
<Button
icon={{
// children is now `any` and needs to be asserted as `SlotRenderFunction`
children: ((Component, props) => <Component {...props} />) satisfies SlotRenderFunction<
React.ComponentProps<'span'>
>,
}}
>
Label
</Button>;
Full support starting @fluentui/react-components v9.72.2.
💡 Follow official React 19 migration guidelines
NONE
📚 For Library Authors & FluentUI Extension Developers
These recommendations ensure your library's TypeScript types remain backwards compatible across React 17, 18, and 19.
React 19 made removed global JSX type, that can cause type compatibility issues across versions.
Always explicitly type your APIs that return JSX markup (render functions, hooks).
Setup ESLint Rule:
{
'@typescript-eslint/explicit-module-boundary-types': [
'error',
{
allowArgumentsExplicitlyTypedAsAny: true,
allowOverloadFunctions: true,
},
],
}
Why? This prevents implicit return type inference that may differ between React versions, ensuring your component and hook signatures remain consistent.
React's JSX namespace types changed between versions. FluentUI provides stable, cross-compatible type utilities that work across React 17, 18, and 19.
Setup ESLint Rule:
Configure @typescript-eslint/no-restricted-types to enforce FluentUI types. View complete setup
Migration Example:
❌ Before (React-specific types):
const renderFoo = (): JSX.Element => <div>Hello</div>;
interface SomeElementProps {
as?: keyof JSX.IntrinsicElements;
divProps?: JSX.IntrinsicElements['div'];
}
✅ After (FluentUI cross-version types):
import type { JSXElement, JSXIntrinsicElementKeys, JSXIntrinsicElement } from '@fluentui/react-components';
const renderFoo = (): JSXElement => <div>Hello</div>;
interface SomeElementProps {
as?: JSXIntrinsicElementKeys;
divProps?: JSXIntrinsicElement<'div'>;
}
Available Types:
JSXElement - Replaces JSX.Element / React.JSX.ElementJSXIntrinsicElementKeys - Replaces keyof JSX.IntrinsicElementsJSXIntrinsicElement<K> - Replaces JSX.IntrinsicElements[K]Benefits:
@types/react version