Development

SPFx with React 18 and Fluent UI v9: Modern Extension Patterns for 2026

The SPFx stack has modernized significantly. A practical guide to building SharePoint Framework extensions with React 18, Fluent UI v9, TypeScript 5, and current performance patterns.

SharePoint Support TeamApril 21, 202612 min read
SPFx with React 18 and Fluent UI v9: Modern Extension Patterns for 2026 - Development guide by SharePoint Support
SPFx with React 18 and Fluent UI v9: Modern Extension Patterns for 2026 - Expert Development guidance from SharePoint Support

The Modern SPFx Stack

SharePoint Framework (SPFx) has evolved significantly in the last 18 months. The current shipping generation supports React 18, Fluent UI v9, TypeScript 5.x, Node 22, and ES2022 target. For developers who built SPFx solutions on React 16 and Fluent UI v8 three years ago, the toolchain, the component library, and the patterns have all changed.

SharePoint architecture diagram showing hub sites, team sites, and content structure
Enterprise SharePoint architecture with hub sites and connected team sites

This guide walks through modern SPFx development patterns, the specific breaking changes between React 16 and React 18 that matter for SPFx, the Fluent UI v9 component model, TypeScript 5 features that improve SPFx code quality, and the performance patterns that produce production-quality extensions.

The Generator and Scaffold

Start every new solution with the latest Yeoman generator for SharePoint Framework. The scaffold produces a solution structure that is compatible with modern tooling and includes ESLint, Jest, Webpack 5, and Node 22 support.

```bash

# Install the latest SPFx generator globally

npm install -g @microsoft/generator-sharepoint@latest

# Scaffold a new solution

mkdir my-spfx-solution

cd my-spfx-solution

yo @microsoft/sharepoint

```

The generator prompts for solution type (web part, extension, library), framework preference (React recommended), and Node version. Select React 18 and TypeScript 5 when prompted. The resulting package.json targets the current supported versions and includes the necessary polyfills.

React 18 in SPFx: What Changed and Why It Matters

React 18 introduced concurrent rendering, automatic batching, Suspense improvements, and a new root API. The changes that matter for SPFx developers specifically:

The New Root API

React 18 requires calling createRoot to mount components. The legacy ReactDOM.render API is deprecated. SPFx web parts must use the new pattern.

```typescript

import * as React from 'react';

import { createRoot, Root } from 'react-dom/client';

import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';

import MyComponent from './components/MyComponent';

export default class MyWebPart extends BaseClientSideWebPart {

private _root: Root | null = null;

public render(): void {

if (!this._root) {

this._root = createRoot(this.domElement);

}

this._root.render(

React.createElement(MyComponent, {

description: this.properties.description,

context: this.context,

})

);

}

protected onDispose(): void {

this._root?.unmount();

this._root = null;

}

}

```

The critical detail is keeping the root reference across renders. Creating a new root on every render causes memory leaks and performance issues. Unmounting in onDispose prevents leaks when the web part is removed.

Automatic Batching

React 18 batches state updates across promises, setTimeouts, and native event handlers automatically. This improves performance but changes behavior for code that relied on synchronous state updates. The common symptom is state that was expected to update after an async operation but appears to update on a later render.

The fix is usually straightforward: code that depended on flushed state should use useEffect or await a microtask. In rare cases flushSync is the right answer, but reach for it only when batching produces a visible rendering problem.

Concurrent Features

Concurrent rendering allows React to interrupt, pause, and resume rendering work. For SPFx, the practical benefits come from useTransition and useDeferredValue. These hooks let expensive operations (large list filtering, heavy computations) run without blocking user input.

```typescript

import * as React from 'react';

import { useState, useTransition, useDeferredValue } from 'react';

export const FilterableList: React.FC<{ items: Item[] }> = ({ items }) => {

const [query, setQuery] = useState('');

const [isPending, startTransition] = useTransition();

const deferredQuery = useDeferredValue(query);

const filtered = React.useMemo(

() => items.filter(i => i.name.toLowerCase().includes(deferredQuery.toLowerCase())),

[items, deferredQuery]

);

return (

value={query}

onChange={(e) => {

const value = e.target.value;

startTransition(() => setQuery(value));

}}

/>

{isPending &&

Filtering...
}

    {filtered.map(item =>

  • {item.name}
  • )}

);

};

```

Fluent UI v9: A Different Component Library

Fluent UI v9 is not a version update of Fluent UI v8. It is a rewrite built on Griffel (a CSS-in-JS solution) with a new component model, new theming system, and new bundle strategy. SPFx solutions can use either v8 (via @fluentui/react) or v9 (via @fluentui/react-components). They can even mix them during migration, though that increases bundle size significantly.

Why v9

Fluent UI v9 was designed for modern performance requirements. Components are tree-shakable, bundles are smaller, theming is token-based and dynamic, and the rendering approach plays better with React 18's concurrent features. For new SPFx solutions, v9 is the preferred choice.

The v9 Component Model

v9 components follow a consistent API pattern: a primary component, slot APIs for customization, and tokens for theming. A typical usage:

```typescript

import * as React from 'react';

import {

FluentProvider,

webLightTheme,

Button,

Card,

CardHeader,

Text,

makeStyles,

tokens,

} from '@fluentui/react-components';

const useStyles = makeStyles({

container: {

padding: tokens.spacingVerticalL,

backgroundColor: tokens.colorNeutralBackground1,

},

title: {

color: tokens.colorNeutralForeground1,

marginBottom: tokens.spacingVerticalM,

},

});

export const ModernWebPartComponent: React.FC = () => {

const styles = useStyles();

return (

header={Modern SPFx}

/>

);

};

```

Theme Integration With SharePoint

SPFx solutions must respect the SharePoint theme, including light mode, dark mode, and high contrast. The SharePoint context provides theme information that can be mapped to Fluent v9 themes.

The typical pattern is reading the current SharePoint theme from the context, selecting the matching Fluent v9 theme (webLightTheme, webDarkTheme, teamsLightTheme, teamsDarkTheme), and wrapping the component tree in a FluentProvider with that theme. A production implementation should also listen for theme change events and re-render when the user changes the site theme.

TypeScript 5: Features That Matter for SPFx

TypeScript 5 brings several features that improve SPFx code quality.

Decorators (Stage 3)

Stage 3 decorators are stable and replace the older experimental decorators. SPFx generator output now uses Stage 3 decorators by default. Custom decorator libraries need to be updated if they rely on the older decorator model.

const Type Parameters

const type parameters preserve literal types in generic functions, which improves IntelliSense and reduces the need for as const assertions in many SPFx patterns.

satisfies Operator

The satisfies operator validates that a value matches a type without widening the inferred type. This is particularly useful for SPFx property pane configurations and Graph API query definitions where you want both type safety and preserved literal types.

```typescript

import { IPropertyPaneConfiguration } from '@microsoft/sp-property-pane';

const propertyPaneConfig = {

pages: [

{

header: { description: 'Configure the web part' },

groups: [

{

groupName: 'Data source',

groupFields: [

{ label: 'Site URL' },

{ label: 'List title' },

],

},

],

},

],

} satisfies IPropertyPaneConfiguration;

```

Performance Patterns That Produce Fast Extensions

Modern SPFx extensions must hit tight performance budgets. A web part that takes 800ms to render degrades the entire page's Core Web Vitals score. Four performance patterns consistently matter.

Pattern 1: Code Splitting

Use dynamic imports for heavy dependencies. A web part that needs a charting library should not import it eagerly. Dynamic imports ensure the chart library only loads when the web part is actually rendered.

Pattern 2: Request Batching

Multiple Microsoft Graph requests should be batched using @microsoft/sp-http request batching or Graph JavaScript SDK batch support. A typical web part that lists user information, site information, and list items should issue one batched request rather than three serial requests.

Pattern 3: Caching with SWR Patterns

Cache remote data using stale-while-revalidate (SWR) patterns. The web part renders from cache immediately, then issues a background request to refresh the data. Libraries like SWR and TanStack Query implement this pattern natively.

Pattern 4: Lazy Rendering

Defer rendering of below-the-fold content until the user scrolls near it. IntersectionObserver is the standard mechanism. For web parts that render a large list, rendering only the first 20 items immediately and loading the rest on scroll reduces initial render time dramatically.

Testing Modern SPFx Solutions

Automated testing is non-negotiable for production SPFx. The standard stack:

  • Jest: Unit testing framework
  • @testing-library/react: Component testing
  • MSW (Mock Service Worker): API mocking for Graph and SharePoint REST calls
  • Playwright: End-to-end testing in a real browser

Target 80 percent code coverage at the business logic layer and 100 percent coverage of utility functions. End-to-end tests should cover the 3 to 5 critical user flows of the extension.

Deployment and Lifecycle

Modern SPFx solutions follow a CI/CD deployment pipeline. The pattern that works:

  • Source code in Git with feature branch workflow
  • Pull request builds that run lint, type check, and unit tests
  • Merge to main triggers a build that produces the SPFx package
  • Deployment to a tenant-wide app catalog goes through a release pipeline with manual approval
  • Post-deployment smoke tests validate the package in the target environment

Azure DevOps and GitHub Actions both have first-class support for SPFx builds. The official Microsoft documentation includes sample pipeline definitions that cover the full lifecycle.

Getting Started

The fastest path to a production-quality SPFx extension is to start with the modern scaffold, port any existing React 16 / Fluent v8 patterns to React 18 / Fluent v9 intentionally (not mechanically), and instrument the extension from day one with performance telemetry and automated tests.

Our SharePoint specialists build modern SPFx extensions for enterprise customers across regulated industries. Contact our team to scope an SPFx development engagement, or review our SharePoint consulting services for architecture and delivery support.

Share this article:

Written by the SharePoint Support Team

Senior SharePoint Consultants | 25+ Years Microsoft Ecosystem Experience

Our senior SharePoint consultants bring deep expertise spanning 500+ enterprise migrations and compliance implementations across HIPAA, SOC 2, and FedRAMP environments. We cover SharePoint Online, Microsoft 365, migrations, Copilot readiness, and large-scale governance.

Frequently Asked Questions

What React version does SPFx support in 2026?
Current SPFx generator versions support React 18 natively. React 18 brings concurrent rendering, automatic batching, Suspense improvements, and the new createRoot API. SPFx solutions built on React 16 can continue running but new development should target React 18 to take advantage of concurrent features and improved performance.
Should we use Fluent UI v8 or v9 for new SPFx web parts?
Fluent UI v9 is the preferred choice for new SPFx solutions. It was designed for modern performance requirements with smaller tree-shakable bundles, token-based theming, and better compatibility with React 18 concurrent features. Fluent UI v8 remains supported and may be required when migrating existing solutions incrementally or when using components not yet available in v9.
Can we mix Fluent UI v8 and v9 in the same SPFx solution?
Yes, the two libraries can coexist in the same bundle, which is useful during incremental migration. The tradeoff is bundle size. Mixing both libraries typically adds 80 to 150 KB to the initial bundle. Plan the migration as a time-boxed project so you do not maintain both libraries indefinitely.
What is the correct way to render a React component in SPFx 2026?
Use the React 18 createRoot API. Create the root once during initial render, cache the root reference on the web part instance, call root.render with the component tree on subsequent renders, and call root.unmount in the web part's onDispose method to prevent memory leaks. The legacy ReactDOM.render API is deprecated and should not be used in new code.
How do we handle SharePoint theme changes in Fluent UI v9 components?
Read the SharePoint theme from the SPFx context, map the theme attributes to the appropriate Fluent UI v9 theme (webLightTheme, webDarkTheme, teamsLightTheme, etc.), and wrap the component tree in a FluentProvider. Listen for theme change events from the SPFx context and re-render the FluentProvider with the updated theme so the component responds to runtime theme changes.
What bundle size budget should SPFx web parts target?
Production SPFx web parts should target an initial bundle under 200 KB compressed. Heavy dependencies such as charting libraries, rich text editors, or data grids should be loaded via dynamic imports rather than included in the initial bundle. Use webpack bundle analyzer to profile bundle size during development and establish a performance budget that the CI pipeline enforces.
Can SPFx solutions use TypeScript 5 features?
Yes. Current SPFx generator versions support TypeScript 5.x. Features including the satisfies operator, const type parameters, and stable decorators are available for use. The tsconfig.json produced by the generator targets appropriate ES version and library settings. Ensure your IDE is configured with a matching TypeScript version to get correct IntelliSense and error highlighting.
What testing framework works best for modern SPFx solutions?
The standard stack is Jest for unit tests, @testing-library/react for component tests, Mock Service Worker (MSW) for mocking Graph and SharePoint REST calls, and Playwright for end-to-end browser tests. Target 80 percent code coverage at the business logic layer and 100 percent coverage for utility functions. End-to-end tests should cover the three to five critical user flows of the extension.

Need Expert Help?

Our SharePoint consultants are ready to help you implement these strategies in your organization.