ReleaseMicrosoftMicrosoftpublished Sep 30, 2025seen Jun 26

microsoft/FluidFramework client_v2.62.0

microsoft/FluidFramework

Open original ↗

Captured source

source ↗
published Sep 30, 2025seen Jun 26captured 5dhttp 200method plain

Fluid Framework v2.62.0 (minor)

Repository: microsoft/FluidFramework

Tag: client_v2.62.0

Published: 2025-09-30T19:41:35Z

Prerelease: no

Release notes:

Contents

  • [🚨 Breaking Changes](#user-content--breaking-changes)
  • [The exports of @fluid-experimental/tree-react-api have been moved to the new @fluidframework/react package and placed under its /alpha exports (#25542)](#user-content-the-exports-of-fluid-experimentaltree-react-api-have-been-moved-to-the-new-fluidframeworkreact-package-and-placed-under-its-alpha-exports-25542)
  • [🌳 SharedTree DDS Changes](#user-content--sharedtree-dds-changes)
  • [Added APIs for tracking observations of SharedTree content for automatic invalidation (#25459)](#user-content-added-apis-for-tracking-observations-of-sharedtree-content-for-automatic-invalidation-25459)
  • [Remove JsonValidator (#25381)](#user-content-remove-jsonvalidator-25381)
  • [Add configuredSharedTreeBeta (#25531)](#user-content-add-configuredsharedtreebeta-25531)
  • [⚠️ Deprecations](#user-content-️-deprecations)
  • [asTreeViewAlpha has been deprecated in favor of asAlpha. (#25512)](#user-content-astreeviewalpha-has-been-deprecated-in-favor-of-asalpha-25512)
  • [Move IPersistedCache types to driver-definitions (#25518)](#user-content-move-ipersistedcache-types-to-driver-definitions-25518)

🚨 Breaking Changes

The exports of @fluid-experimental/tree-react-api have been moved to the new @fluidframework/react package and placed under its /alpha exports (#25542)

@fluid-experimental/tree-react-api has been adjusted to align with Fluid Framework's API Support Levels. It has been renamed to @fluidframework/react and all existing APIs are now available under @fluidframework/react/alpha.

Since this package was under @fluid-experimental, previously it implicitly made no guarantees. Now all the APIs are @alpha, which also amounts to making no guarantees but makes it possible to promote APIs to @beta in the future to offer some stability.

To accommodate this change, all users of this package will need to adjust:

  • Package dependencies from "@fluid-experimental/tree-react-api" to "@fluidframework/react".
  • Imports from "@fluid-experimental/tree-react-api" to "@fluidframework/react/alpha".

Change details

Commit: `b388c7b`

Affected packages:

  • @fluid-experimental/tree-react-api
  • @fluidframework/react

[⬆️ Table of contents](#user-content-contents)

🌳 SharedTree DDS Changes

Added APIs for tracking observations of SharedTree content for automatic invalidation (#25459)

TreeAlpha.trackObservations and TreeAlpha.trackObservationsOnce have been added. These provide a way to run some operation which reads content from TreeNodes, then run a call back when anything observed by that operation changes.

This functionality has also been exposed in the form of React hooks and React higher order components via the @fluid-experimental/tree-react-api package. It is now possible to use these utilities to implement React applications which pass TreeNodes in their props and get all necessary invalidation from tree changes handled automatically. The recommended pattern for doing this is to use treeDataObject or TreeViewComponent at the root, then withTreeObservations or withMemoizedTreeObservations for any sub-components which read from TreeNodes. Alternatively more localized changes can be made by using PropNode to type erase TreeNodes passed in props, then use one of the usePropTreeNode or usePropTreeRecord hooks to read from them.

These APIs work with both hydrated and un-hydrated TreeNodes.

React Support

Here is a simple example of a React components which has an invalidation bug due to reading a mutable field from a TreeNode that was provided in a prop:

const builder = new SchemaFactory("example");
class Item extends builder.object("Item", { text: SchemaFactory.string }) {}
const ItemComponentBug = ({ item }: { item: Item }): JSX.Element => (
{item.text} // Reading `text`, a mutable value from a React prop, causes an invalidation bug.
);

This bug can now easily be fixed using withTreeObservations or withMemoizedTreeObservations:

const ItemComponent = withTreeObservations(
({ item }: { item: Item }): JSX.Element => {item.text},
);

For components which take in TreeNodes, but merely forward them and do not read their properties, they can use PropTreeNode as shown:

const ItemParentComponent = ({ item }: { item: PropTreeNode }): JSX.Element => (

);

If such a component reads from the TreeNode, it gets a compile error instead of an invalidation bug. In this case the invalidation bug would be that if item.text is modified, the component would not re-render.

const InvalidItemParentComponent = ({
item,
}: { item: PropTreeNode }): JSX.Element => (
// @ts-expect-error PropTreeNode turns this invalidation bug into a compile error
{item.text}
);

To provide access to TreeNode content in only part of a component the usePropTreeNode or usePropTreeRecord hooks can be used.

TreeAlpha.trackObservationsOnce Examples

Here is a rather minimal example of how TreeAlpha.trackObservationsOnce can be used:

cachedFoo ??= TreeAlpha.trackObservationsOnce(
() => {
cachedFoo = undefined;
},
() => nodeA.someChild.bar + nodeB.someChild.baz,
).result;

That is equivalent to doing the following:

if (cachedFoo === undefined) {
cachedFoo = nodeA.someChild.bar + nodeB.someChild.baz;
const invalidate = (): void => {
cachedFoo = undefined;
for (const u of unsubscribe) {
u();
}
};
const unsubscribe: (() => void)[] = [
TreeBeta.on(nodeA, "nodeChanged", (data) => {
if (data.changedProperties.has("someChild")) {
invalidate();
}
}),
TreeBeta.on(nodeB, "nodeChanged", (data) => {
if (data.changedProperties.has("someChild")) {
invalidate();
}
}),
TreeBeta.on(nodeA.someChild, "nodeChanged", (data) => {
if (data.changedProperties.has("bar")) {
invalidate();
}
}),
TreeBeta.on(nodeB.someChild, "nodeChanged", (data) => {
if...

Excerpt shown — open the source for the full document.