@fluidframework/react Package
Utilities for using SharedTree with React.
Interfaces
| Interface | Alerts | Modifiers | Description |
|---|---|---|---|
| IReactTreeDataObject | Alpha | sealed | A schema-aware tree-backed DataObject, extended with a React Component to view the tree. |
| ObservationOptions | Alpha | Options for useTreeObservations(trackDuring, options). | |
| PropTreeNode | Alpha | A type erased TreeNode for use in react props. | |
| SchemaIncompatibleProps | Alpha | React Props for displaying when the opened document is incompatible with the required view schema. | |
| SynchronizedString | Alpha | sealed | The value returned by useTreeSynchronizedString(tree, initialSelection). |
| TextSelection | Alpha | A text selection or cursor range expressed as UTF-16 code-unit offsets. | |
| TreeViewProps | Alpha | React props for viewing a tree. |
Types
| TypeAlias | Alerts | Description |
|---|---|---|
| IsMappableObjectType | System | Detect if a type is a simple structural object. |
| NodeRecord | Alpha | Record that can contain TreeNodes. |
| PropTreeNodeRecord | Alpha | Type erase TreeNodes from a NodeRecord as a PropTreeNode. |
| PropTreeValue | Alpha | Type erase a TreeNode from a TreeNode | TreeLeafValue as a PropTreeNode. |
| UnwrapPropTreeNode | Alpha | Casts a node from a PropTreeNode back to a TreeNode. |
| UnwrapPropTreeNodeRecord | Alpha | Type erase TreeNodes from a NodeRecord as a PropTreeNode. |
| WrapNodes | Alpha | Type TreeNodes in T as PropTreeNodes. |
| WrapPropTreeNodeRecord | Alpha | Type erase TreeNodes from a NodeRecord as a PropTreeNode. |
Functions
| Function | Alerts | Return Type | Description |
|---|---|---|---|
| objectIdNumber(object) | Alpha | number | Associates a unique number with an object. |
| syncTextToTree(root, newText) | Alpha | void | Sync newText into the provided root tree by applying the minimal remove + insert pair needed to transform the tree's current content into newText. |
| toPropTreeNode(node) | Alpha | PropTreeValue<T> | Type erase a TreeNode as a PropTreeNode. |
| toPropTreeRecord(node) | Alpha | WrapPropTreeNodeRecord<T> | Type erase a NodeRecord as a PropTreeNodeRecord. |
| treeDataObject(treeConfiguration, createInitialTree) | Alpha | SharedObjectKind<IReactTreeDataObject<TSchema> & IFluidLoadable> | Defines a DataObject for a SharedTree with a built in TreeViewConfiguration. |
| TreeViewComponent({ tree, viewComponent: ViewComponent, errorComponent, }, input) | Alpha | JSX.Element | React component which handles schematizing trees. This includes displaying errors when the document can not be schematized. |
| unwrapPropTreeNode(propNode) | Alpha | T | Casts a node from a PropTreeNode back to a TreeNode. |
| unwrapPropTreeRecord(props) | Alpha | UnwrapPropTreeNodeRecord<T> | unwrapPropTreeNode(propNode) but for a PropTreeNodeRecord. |
| usePropTreeNode(propNode, trackDuring) | Alpha | WrapNodes<TResult> | Custom hook for using a prop tree node. |
| usePropTreeRecord(props, f) | Alpha | WrapNodes<TResult> | usePropTreeNode(propNode, trackDuring) but takes in a PropTreeNodeRecord. |
| useTree(subtreeRoot) | Alpha | number | Custom hook which invalidates a React Component when there is a change in the subtree defined by subtreeRoot. This includes changes to the tree's content, but not changes to its parentage. See treeChanged() for details. |
| useTreeObservations(trackDuring, options) | Alpha | TResult | Custom hook which invalidates a React Component when there is a change in tree content observed during trackDuring. |
| useTreeSynchronizedString(tree, initialSelection) | Alpha | SynchronizedString | React hook that provides a one-way sync from a @fluidframework/tree#PlainText.Tree to a string: it returns the tree's current text (and a tracked selection), recomputed whenever the tree's characters change. |
| withMemoizedTreeObservations(component, options) | Alpha | MemoExoticComponent<ReturnType<typeof withTreeObservations<TIn>>> | withTreeObservations(component, options) wrapped with memo. |
| withTreeObservations(component, options) | Alpha | FC<TIn> & FC<WrapNodes<TIn>> & FC<TIn | WrapNodes<TIn>> | Higher order component which wraps a component to use useTreeObservations(trackDuring, options). |
Function Details
objectIdNumber
Associates a unique number with an object.
To use, import via @fluidframework/react/alpha.
For more information about our API support guarantees, see here.
Signature
export declare function objectIdNumber(object: object): number;
Remarks
The ID number is tied to the object identity, not the object's contents; modifying the object will not cause it to get a different ID.
This can be handy for generating keys for React lists from TreeNodes.
Most cases which could use this function should just use the objects themselves instead of getting IDs from them, since the objects will have the same equality as the IDs. For example, if storing data associated with the objects in a map, using the object as the key is more efficient than getting an ID from it and using that. This functions exists to deal with the edge case where you would like to use object identity, but you can't. React keys are an examples of such a case, since React does not allow objects as keys.
Parameters
| Parameter | Type | Description |
|---|---|---|
| object | object |
Returns
Return type: number
syncTextToTree
Sync newText into the provided root tree by applying the minimal remove + insert pair needed to transform the tree's current content into newText.
To use, import via @fluidframework/react/alpha.
For more information about our API support guarantees, see here.
Signature
export declare function syncTextToTree(root: PlainText.Tree, newText: string): void;
Remarks
The diff is computed by finding the longest shared prefix/suffix between current and new content and replacing only the middle span. The resulting remove + insert pair is wrapped in a transaction internally, so a single call applies (and undoes/redoes) as one atomic unit.
Example
Avoiding re-entrant edits
Mutating the tree synchronously fires onCharactersChanged(callback). If you also subscribe to that event to apply remote edits to your view, set a re-entrancy flag before calling this and ignore the event while it is set — otherwise the edit you just made is echoed straight back onto your view:
let updating = false;
root.onCharactersChanged((ops) => {
if (updating) return; // ignore the echo of our own local edit
// ...apply ops to your view...
});
function onUserInput(newText: string): void {
updating = true;
try {
syncTextToTree(root, newText);
} finally {
updating = false;
}
}
Parameters
| Parameter | Type | Description |
|---|---|---|
| root | PlainText.Tree | |
| newText | string |
toPropTreeNode
Type erase a TreeNode as a PropTreeNode.
To use, import via @fluidframework/react/alpha.
For more information about our API support guarantees, see here.
Signature
export declare function toPropTreeNode<T extends TreeNode | TreeLeafValue>(node: T): PropTreeValue<T>;
Type Parameters
| Parameter | Constraint | Description |
|---|---|---|
| T | TreeNode | TreeLeafValue |
Parameters
| Parameter | Type | Description |
|---|---|---|
| node | T |
Returns
Return type: PropTreeValue<T>
toPropTreeRecord
Type erase a NodeRecord as a PropTreeNodeRecord.
To use, import via @fluidframework/react/alpha.
For more information about our API support guarantees, see here.
Signature
export declare function toPropTreeRecord<T extends NodeRecord>(node: T): WrapPropTreeNodeRecord<T>;
Type Parameters
| Parameter | Constraint | Description |
|---|---|---|
| T | NodeRecord |
Parameters
| Parameter | Type | Description |
|---|---|---|
| node | T |
Returns
Return type: WrapPropTreeNodeRecord<T>
treeDataObject
Defines a DataObject for a SharedTree with a built in TreeViewConfiguration.
To use, import via @fluidframework/react/alpha.
For more information about our API support guarantees, see here.
Signature
export declare function treeDataObject<TSchema extends ImplicitFieldSchema>(treeConfiguration: TreeViewConfiguration<TSchema>, createInitialTree: () => InsertableTreeFieldFromImplicitField<TSchema>): SharedObjectKind<IReactTreeDataObject<TSchema> & IFluidLoadable>;
Type Parameters
| Parameter | Constraint | Description |
|---|---|---|
| TSchema | ImplicitFieldSchema |
Parameters
| Parameter | Type | Description |
|---|---|---|
| treeConfiguration | TreeViewConfiguration<TSchema> | See config. |
| createInitialTree | () => InsertableTreeFieldFromImplicitField<TSchema> | Function which populates the tree with initial data on document create. |
Returns
A @fluidframework/fluid-static#DataObjectClass to allow easy use of a SharedTree in a ContainerSchema.
Return type: SharedObjectKind<IReactTreeDataObject<TSchema> & IFluidLoadable>
TreeViewComponent
React component which handles schematizing trees. This includes displaying errors when the document can not be schematized.
To use, import via @fluidframework/react/alpha.
For more information about our API support guarantees, see here.
Signature
export declare function TreeViewComponent<TSchema extends ImplicitFieldSchema>(input: TreeViewProps<TSchema> & {
tree: Pick<IReactTreeDataObject<TSchema>, "treeView">;
}): JSX.Element;
Type Parameters
| Parameter | Constraint | Description |
|---|---|---|
| TSchema | ImplicitFieldSchema |
Parameters
| Parameter | Type | Description |
|---|---|---|
| { tree, viewComponent: ViewComponent, errorComponent, } | ||
| input | TreeViewProps<TSchema> & { tree: Pick<IReactTreeDataObject<TSchema>, "treeView">; } |
Returns
Return type: JSX.Element
unwrapPropTreeNode
Casts a node from a PropTreeNode back to a TreeNode.
To use, import via @fluidframework/react/alpha.
For more information about our API support guarantees, see here.
Signature
export declare function unwrapPropTreeNode<T extends TreeNode | TreeLeafValue>(propNode: PropTreeValue<T> | T): T;
Type Parameters
| Parameter | Constraint | Description |
|---|---|---|
| T | TreeNode | TreeLeafValue |
Remarks
This should only be done in scenarios where tracking observations is not required (such as event handlers), or when taking care to handle invalidation manually.
Parameters
| Parameter | Type | Description |
|---|---|---|
| propNode | PropTreeValue<T> | T |
Returns
Return type: T
unwrapPropTreeRecord
unwrapPropTreeNode(propNode) but for a PropTreeNodeRecord.
To use, import via @fluidframework/react/alpha.
For more information about our API support guarantees, see here.
Signature
export declare function unwrapPropTreeRecord<T extends PropTreeNodeRecord>(props: T): UnwrapPropTreeNodeRecord<T>;
Type Parameters
| Parameter | Constraint | Description |
|---|---|---|
| T | PropTreeNodeRecord |
Parameters
| Parameter | Type | Description |
|---|---|---|
| props | T |
Returns
Return type: UnwrapPropTreeNodeRecord<T>
usePropTreeNode
Custom hook for using a prop tree node.
To use, import via @fluidframework/react/alpha.
For more information about our API support guarantees, see here.
Signature
export declare function usePropTreeNode<T extends TreeNode | TreeLeafValue, TResult>(propNode: PropTreeValue<T> | T, trackDuring: (node: T) => TResult): WrapNodes<TResult>;
Type Parameters
| Parameter | Constraint | Description |
|---|---|---|
| T | TreeNode | TreeLeafValue | |
| TResult |
Remarks
Reads content using useTreeObservations(trackDuring, options) to track dependencies.
Parameters
| Parameter | Type | Description |
|---|---|---|
| propNode | PropTreeValue<T> | T | Input, automatically unwrapped TreeNode from a PropTreeNode if needed. |
| trackDuring | (node: T) => TResult | Callback which reads from the node and returns a result. If the result is a TreeNode or NodeRecord it will be wrapped as a PropTreeNode or PropTreeNodeRecord, see WrapNodes. It is recommended that when returning data containing TreeNodes, use a format supported by WrapNodes or wrap the nodes manually using toPropTreeNode(node). This improves the type safety, reducing the risk of invalidation bugs due to untracked access of tree content contained in the return value. Note that is is fine to observe any node inside the callback, not just the provided node: all accesses will be tracked. The input node is just provided as a way to automatically unwrap the PropTreeNode |
Returns
Return type: WrapNodes<TResult>
usePropTreeRecord
usePropTreeNode(propNode, trackDuring) but takes in a PropTreeNodeRecord.
To use, import via @fluidframework/react/alpha.
For more information about our API support guarantees, see here.
Signature
export declare function usePropTreeRecord<const T extends PropTreeNodeRecord, TResult>(props: T, f: (node: UnwrapPropTreeNodeRecord<T>) => TResult): WrapNodes<TResult>;
Type Parameters
| Parameter | Constraint | Description |
|---|---|---|
| T | PropTreeNodeRecord | |
| TResult |
Parameters
| Parameter | Type | Description |
|---|---|---|
| props | T | |
| f | (node: UnwrapPropTreeNodeRecord<T>) => TResult |
Returns
Return type: WrapNodes<TResult>
useTree
Custom hook which invalidates a React Component when there is a change in the subtree defined by subtreeRoot. This includes changes to the tree's content, but not changes to its parentage. See treeChanged() for details.
To use, import via @fluidframework/react/alpha.
For more information about our API support guarantees, see here.
Signature
export declare function useTree(subtreeRoot: TreeNode): number;
Remarks
Consider using useTreeObservations(trackDuring, options) instead which tracks what was observed and only invalidates if it changes.
Parameters
| Parameter | Type | Description |
|---|---|---|
| subtreeRoot | TreeNode |
Returns
Return type: number
useTreeObservations
Custom hook which invalidates a React Component when there is a change in tree content observed during trackDuring.
To use, import via @fluidframework/react/alpha.
For more information about our API support guarantees, see here.
Signature
export declare function useTreeObservations<TResult>(trackDuring: () => TResult, options?: ObservationOptions): TResult;
Type Parameters
| Parameter | Description |
|---|---|
| TResult |
Remarks
This includes changes to the tree's content. Currently this will throw if observing a node's parentage to be undefined, and node status changes will not cause invalidation.
For additional type safety to help avoid observing TreeNode content outside of this hook, see PropTreeNode.
Parameters
| Parameter | Modifiers | Type | Description |
|---|---|---|---|
| trackDuring | () => TResult | Called synchronously, and will have its tree observations tracked. | |
| options | optional | ObservationOptions |
Returns
Return type: TResult
useTreeSynchronizedString
React hook that provides a one-way sync from a @fluidframework/tree#PlainText.Tree to a string: it returns the tree's current text (and a tracked selection), recomputed whenever the tree's characters change.
To use, import via @fluidframework/react/alpha.
For more information about our API support guarantees, see here.
Signature
export declare function useTreeSynchronizedString(tree: PlainText.Tree, initialSelection?: TextSelection): SynchronizedString;
Remarks
This makes no assumption about how the string is rendered (<input>, <textarea>, contenteditable, canvas, …) and intentionally does **not** handle writing back to the tree.
The consumer supplies the other direction (string → tree) themselves. Different text APIs report their edits in different formats, so there is no one-size-fits-all mapping; prefer translating the API's own change delta into an incremental tree edit whenever it exposes one. For simple APIs like <textarea>, whose change events only surface the fully-updated string, syncTextToTree(root, newText) provides a naive diff-and-apply that is sufficient (wrap it in a transaction to make the edit atomically undoable):
const { text } = useTreeSynchronizedString(tree);
return (
<textarea
value={text}
onChange={(e) =>
TreeAlpha.context(tree).runTransaction(() => syncTextToTree(tree, e.target.value))
}
/>
);
Parameters
| Parameter | Modifiers | Type | Description |
|---|---|---|---|
| tree | PlainText.Tree | ||
| initialSelection | optional | TextSelection |
Returns
Return type: SynchronizedString
withMemoizedTreeObservations
withTreeObservations(component, options) wrapped with memo.
To use, import via @fluidframework/react/alpha.
For more information about our API support guarantees, see here.
Signature
export declare function withMemoizedTreeObservations<TIn>(component: FC<TIn>, options?: ObservationOptions & {
readonly propsAreEqual?: Parameters<typeof memo>[1];
}): MemoExoticComponent<ReturnType<typeof withTreeObservations<TIn>>>;
Type Parameters
| Parameter | Description |
|---|---|
| TIn |
Remarks
There is no special logic here, just a convenience wrapper.
Parameters
| Parameter | Modifiers | Type | Description |
|---|---|---|---|
| component | FC<TIn> | ||
| options | optional | ObservationOptions & { readonly propsAreEqual?: Parameters<typeof memo>[1]; } |
Returns
Return type: MemoExoticComponent<ReturnType<typeof withTreeObservations<TIn>>>
withTreeObservations
Higher order component which wraps a component to use useTreeObservations(trackDuring, options).
To use, import via @fluidframework/react/alpha.
For more information about our API support guarantees, see here.
Signature
export declare function withTreeObservations<TIn>(component: FC<TIn>, options?: ObservationOptions): FC<TIn> & FC<WrapNodes<TIn>> & FC<TIn | WrapNodes<TIn>>;
Type Parameters
| Parameter | Description |
|---|---|
| TIn |
Remarks
When passing TreeNodes in props, care must be taken to not observe their content outside of a context which does observation tracking (or manual invalidation). This wraps a component in such tracking.
It is recommended that sub-components which take in TreeNodes, if not defined using this higher order components, take the nodes in as PropTreeNodes. Components defined using this higher order component can take in either raw TreeNodes or PropTreeNodes: the latter will be automatically unwrapped.
Parameters
| Parameter | Modifiers | Type | Description |
|---|---|---|---|
| component | FC<TIn> | ||
| options | optional | ObservationOptions |
Returns
Return type: FC<TIn> & FC<WrapNodes<TIn>> & FC<TIn | WrapNodes<TIn>>