Skip to content

React 19 Update #6057

Open
nielsq wants to merge 9 commits into
Azure:mainfrom
nielsq:claude/upgrade-react-19.2-UlMXJ
Open

React 19 Update #6057
nielsq wants to merge 9 commits into
Azure:mainfrom
nielsq:claude/upgrade-react-19.2-UlMXJ

Conversation

@nielsq
Copy link
Copy Markdown

@nielsq nielsq commented May 21, 2026

What

Does anyone still care about this package?
I let AI do all the work for me. Maybe someone picks it up and finishes the job.
Not a single line was read/written or tested. I know it´s slop.

Why

React Version was out of date

How Tested

It is not tested.

Process & policy checklist

  • I have updated the project documentation to reflect my changes if necessary.
  • I have read the CONTRIBUTING documentation.

Is this a breaking change?

  • This change causes current functionality to break.
    New react version

claude added 3 commits May 21, 2026 08:54
- Bump react/react-dom devDependencies to 19.2.6 in all packages and samples
- Bump @types/react to 19.2.15 and @types/react-dom to 19.2.3
- Bump react-is to ^19.2.6
- Widen peer dependency ranges from <19.0.0 to <20.0.0 to accept React 19.x consumers
- Fix 44 useRef<T>(null) → useRef<T | null>(null) across react-components and react-composites
  (React 19 dropped the T|null overload for useRef; RefObject<T>.current is now readonly T)
- Fix createRef<T>() → createRef<T | null>() for the same reason
After the initial React 19.2 version bumps, this commit resolves all
TypeScript type errors introduced by React 19 breaking changes:

- Remove usage of the deleted global JSX namespace: add per-package
  react-jsx-global.d.ts shims that re-export React.JSX types into the
  global JSX namespace for each package's tsconfig include root.

- Fix useRef() no-argument calls (TS2554): React 19 removed the
  zero-argument overload; 9 sites updated to pass explicit undefined or null.

- Fix ReactChild usage (TS2305): React 19 deleted React.ReactChild; two
  files updated to use ReactElement | number | string.

- Fix RefObject<T> prop/param annotations: React 19's useRef<T>(null)
  returns RefObject<T | null> (mutable). Internal prop annotations typed
  as RefObject<T> (non-null) now reject the nullable refs produced by
  callers. Updated annotations in react-components (InputBoxComponent,
  TextFieldWithMention, RichTextInputBoxComponent, MentionPopover,
  ModalClone, responsive.ts, VideoBackgroundEffectsPicker,
  VideoEffectsItem) and react-composites (Camera, CommonCallControlBar,
  PeopleButton, SidePaneHeader, usePeoplePane, useVideoEffectsPane,
  VideoEffectsPane).

- Bump FluentUI v8 minimum ranges to React 19-compatible versions:
  @fluentui/react ^8.125.6, @fluentui/react-hooks ^8.10.2,
  @fluentui/react-icons ^2.0.327, @fluentui/react-window-provider ^2.3.2.

- Add pnpm globalOverrides for @griffel/core@1.21.1 → ^1.21.2 and
  @griffel/react@1.7.3 → ^1.7.4 to work around bad npm publishes that
  shipped raw .ts/.tsx source without .d.ts declarations; these are
  pulled transitively by @fluentui/react-components@9.73.8.

- Add 18 new ColorTokens to v9ThemeShim.ts required by
  @fluentui/react-components@9.73.8.

- Regenerate pnpm-lock.yaml (both default and stable variant) via
  rush update.

Pre-existing failures not caused by this upgrade (Azure SDK beta vs
stable resolution in calling-stateful-client, chat-stateful-client, and
fake-backends) are unchanged and still present after upgrade.

https://claude.ai/code/session_01Gztn9KK8WBqBLD7LrpGcXL
The initial React 19 fix added per-package react-jsx-global.d.ts shims
covered by each tsconfig's main include glob. Two compilations use
narrower includes that did not pick up a shim:

- packages/storybook8/tsconfig.snippets.json only includes
  *.snippet.tsx/.ts files (used by the test:snippets script). Without
  the shim, all snippet files and the paths-mapped package sources they
  import failed with "Cannot find namespace 'JSX'". Added the existing
  stories/react-jsx-global.d.ts to its include list.

- packages/react-composites/tests/tsconfig.json (used by the tsc:e2e
  script) includes only tests/**/*; the shim under src/ was not in
  scope. Added a tests/react-jsx-global.d.ts shim.

https://claude.ai/code/session_01Gztn9KK8WBqBLD7LrpGcXL
@nielsq
Copy link
Copy Markdown
Author

nielsq commented May 22, 2026

@microsoft-github-policy-service agree

@microsoft-github-policy-service agree

claude added 6 commits May 22, 2026 10:11
react-linkify@1.0.0-alpha is an unmaintained 2018 alpha package whose
CJS/ESM interop causes the Linkify class to resolve as a plain object
rather than a component function under certain React 19 bundling
configurations, producing:

  Element type is invalid: expected a string or class/function but got:
  object. Check the render method of ChatMessageContent.

Replace it with an inline URL linkification helper that splits plain-text
content on https?:// URLs and renders each match as a <Link> component
from @fluentui/react, preserving the same visual behavior (links open
in a new tab) without the external dependency.

https://claude.ai/code/session_01Gztn9KK8WBqBLD7LrpGcXL
…rror

The DeviceManager.isSpeakerSelectionAvailable getter can throw a
CallingCommunicationError from the ACS SDK when it is called before the
device manager is fully initialised — in particular when the browser
Permissions API fires a change event and triggers the
permissionsApiStateChangeHandler → updateDevicePermissionState →
setDeviceManager path.

Wrap both call-sites (setDeviceManager and audioDevicesUpdated) in a
try/catch that logs a warning and defaults to false so the state
machinery continues to run without an unhandled exception.

https://claude.ai/code/session_01Gztn9KK8WBqBLD7LrpGcXL
External consumers reach the DeviceManager through the Proxy created by
deviceManagerDeclaratify. The previous fix only guarded internal access
inside ProxyDeviceManager; reads from the adapter layer
(AzureCommunicationCallAdapter.querySpeakers, createAdapterFromClient,
createTeamsCallAdapterFromClient) still fall through to
Reflect.get(target, 'isSpeakerSelectionAvailable') and can hit the same
CallingCommunicationError.

Add an explicit case in the proxy get() handler that mirrors the
internal guard: log a warning and return false when the SDK getter
throws.

Cover both call-sites with regression tests:
  * proxy access returns false (and warns) when the getter throws
  * the audioDevicesUpdated event handler does not propagate the throw

https://claude.ai/code/session_01Gztn9KK8WBqBLD7LrpGcXL
Use optional chaining with numeric fallback (RatingSize?.Large ?? 1) so the
Rating component renders correctly even when the @fluentui/react enum object
is not resolved at the time of access in certain bundler configurations.

https://claude.ai/code/session_01Gztn9KK8WBqBLD7LrpGcXL
…rash

acs-ui-javascript-loaders declared react-dom only as a peer dependency
(>=16.8.0 <20.0.0) without a concrete devDependency pin. pnpm satisfied
that peer with react-dom@18.3.1, creating a @fluentui/react@8.125.6
variant linked against react-dom@18.3.1 alongside react@19.2.6.

That variant fails to evaluate at runtime because react-dom@18.3.1
reaches into React 18 internals (ReactSharedInternals.ReactCurrentDispatcher)
that React 19 removed. When the bundler loads @fluentui/react through the
acs-ui-javascript-loaders dependency chain, the broken variant throws
during module init and the module exports object ends up without
RatingSize, causing _StarSurvey to crash on RatingSize.Large.

Pinning react-dom@19.2.6 and @types/react-dom@19.2.3 in devDependencies
forces pnpm to dedupe @fluentui/react onto the single React 19 variant.
Reverts the unnecessary defensive RatingSize?.Large fallback in
StarSurvey since the root cause is the dependency mismatch.

https://claude.ai/code/session_01Gztn9KK8WBqBLD7LrpGcXL
Bun's bundler doesn't properly resolve @fluentui/react's IIFE enum
pattern in its CJS build (exports.RatingSize = void 0 followed by an
IIFE that fills it in), leaving RatingSize as undefined at runtime and
crashing _StarSurvey when it accesses RatingSize.Large after a call ends.

Switch to import type so no runtime value is imported, and use the
literal 1 (RatingSize.Large's stable numeric value) cast to RatingSize
for TypeScript. The Rating component receives the same value at runtime;
consumers with any bundler are unaffected.

https://claude.ai/code/session_01Gztn9KK8WBqBLD7LrpGcXL
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants