React Migration in Tree View Component

This section explains how to migrate the TreeView component from EJ2 React to React. It provides a detailed comparison of APIs, including props, methods and events.

Properties

EJ2 ReactReactDescription

Props: allowEditing

const dataSource = [ { id: '1', name: 'Documents', hasChild: true }, { id: '2', pid: '1', name: 'Reports' }, { id: '3', pid: '1', name: 'Invoices' } ]; <TreeViewComponent fields={ { dataSource: dataSource, id: 'id', text: 'name', parentID: 'pid', hasChildren: 'hasChild' } } allowEditing={true}></TreeViewComponent>

Props: editable

const dataSource = [ { id: '1', label: 'Documents' }, { id: '2', parentId: '1', label: 'Reports' }, { id: '3', parentId: '1', label: 'Invoices' } ]; <TreeView dataSource={dataSource} editable={true}></TreeView>

The allowEditing prop in EJ2 React is replaced with the editable prop in React.

Props: allowMultiSelection

const dataSource = [ { id: '1', name: 'Documents', hasChild: true }, { id: '2', pid: '1', name: 'Reports' }, { id: '3', pid: '1', name: 'Invoices' } ]; <TreeViewComponent fields={ { dataSource: dataSource, id: 'id', text: 'name', parentID: 'pid', hasChildren: 'hasChild' } } allowMultiSelection={true}></TreeViewComponent>

Props: selectionMode

const dataSource = [ { id: '1', label: 'Documents' }, { id: '2', parentId: '1', label: 'Reports' }, { id: '3', parentId: '1', label: 'Invoices' } ]; <TreeView dataSource={dataSource} selectionMode='Multiple'></TreeView>

The allowMultiSelection prop in EJ2 React is replaced with the selectionMode prop set to 'Multiple' in React.

Props: allowTextWrap

const dataSource = [ { id: '1', name: 'Documents', hasChild: true }, { id: '2', pid: '1', name: 'Reports' }, { id: '3', pid: '1', name: 'Invoices' } ]; <TreeViewComponent fields={ { dataSource: dataSource, id: 'id', text: 'name', parentID: 'pid', hasChildren: 'hasChild' } } allowTextWrap={true}></TreeViewComponent>

Props: textWrap

const dataSource = [ { id: '1', label: 'Documents' }, { id: '2', parentId: '1', label: 'Reports' }, { id: '3', parentId: '1', label: 'Invoices' } ]; <TreeView dataSource={dataSource} textWrap={true}></TreeView>

The allowTextWrap prop in EJ2 React is replaced with the textWrap prop in React.

Props: autoCheck

const dataSource = [ { id: '1', name: 'Documents', hasChild: true, isChecked: true }, { id: '2', pid: '1', name: 'Reports' }, { id: '3', pid: '1', name: 'Invoices' } ]; <TreeViewComponent fields={ { dataSource: dataSource, id: 'id', text: 'name', parentID: 'pid', hasChildren: 'hasChild', isChecked: 'isChecked' } } showCheckBox={true} autoCheck={true}></TreeViewComponent>

Props: autoCheck

const dataSource = [ { id: '1', label: 'Documents', isChecked: true }, { id: '2', parentId: '1', label: 'Reports' }, { id: '3', parentId: '1', label: 'Invoices' } ]; <TreeView dataSource={dataSource} selectionMode='Checkbox' autoCheck={true}></TreeView>

The autoCheck prop is supported in both EJ2 React and React.

Props: checkDisabledChildren

const dataSource = [ { id: '1', name: 'Documents', hasChild: true }, { id: '2', pid: '1', name: 'Reports' }, { id: '3', pid: '1', name: 'Invoices' } ]; <TreeViewComponent fields={ { dataSource: dataSource, id: 'id', text: 'name', parentID: 'pid', hasChildren: 'hasChild' } } showCheckBox={true} checkDisabledChildren={true}></TreeViewComponent>

Props: checkDisabledChildren

const dataSource = [ { id: '1', label: 'Documents' }, { id: '2', parentId: '1', label: 'Reports' }, { id: '3', parentId: '1', label: 'Invoices' } ]; <TreeView dataSource={dataSource} selectionMode='Checkbox' checkDisabledChildren={true}></TreeView>

The checkDisabledChildren prop is supported in both EJ2 React and React.

Props: checkOnClick

const dataSource = [ { id: '1', name: 'Documents', hasChild: true }, { id: '2', pid: '1', name: 'Reports' }, { id: '3', pid: '1', name: 'Invoices' } ]; <TreeViewComponent fields={ { dataSource: dataSource, id: 'id', text: 'name', parentID: 'pid', hasChildren: 'hasChild' } } showCheckBox={true} checkOnClick={true}></TreeViewComponent>

Props: checkOnClick

const dataSource = [ { id: '1', label: 'Documents' }, { id: '2', parentId: '1', label: 'Reports' }, { id: '3', parentId: '1', label: 'Invoices' } ]; <TreeView dataSource={dataSource} selectionMode='Checkbox' checkOnClick={true}></TreeView>

The checkOnClick prop is supported in both EJ2 React and React.

Props: cssClass

const dataSource = [ { id: '1', name: 'Documents', hasChild: true }, { id: '2', pid: '1', name: 'Reports' }, { id: '3', pid: '1', name: 'Invoices' } ]; <TreeViewComponent fields={ { dataSource: dataSource, id: 'id', text: 'name', parentID: 'pid', hasChildren: 'hasChild' } } cssClass='e-custom e-tree'></TreeViewComponent>

Props: className

const dataSource = [ { id: '1', label: 'Documents' }, { id: '2', parentId: '1', label: 'Reports' }, { id: '3', parentId: '1', label: 'Invoices' } ]; <TreeView dataSource={dataSource} className='custom-tree'></TreeView>

The cssClass prop in EJ2 React is replaced with the standard React className prop in React.

Props: dataSource and fields

const hierarchicalData = [ { id: '1', name: 'Documents', hasChild: true }, { id: '2', pid: '1', name: 'Reports' }, { id: '3', pid: '1', name: 'Invoices' } ]; <TreeViewComponent fields={ { dataSource: hierarchicalData, id: 'id', text: 'name', parentID: 'pid', hasChildren: 'hasChild' } }></TreeViewComponent>

Props: dataSource and fields

const dataSource = [ { id: '1', label: 'Documents' }, { id: '2', parentId: '1', label: 'Reports' }, { id: '3', parentId: '1', label: 'Invoices' } ]; <TreeView dataSource={dataSource} fields={ { id: 'id', text: 'label', parentId: 'parentId' } }></TreeView>

The dataSource and fields props are supported in both EJ2 React and React. In React, the dataSource is moved from the fields configuration to the root level of the component, while fields only configures the mapping of datasource field names to Tree View fields.

Props: disabled

const dataSource = [ { id: '1', name: 'Documents', hasChild: true }, { id: '2', pid: '1', name: 'Reports' }, { id: '3', pid: '1', name: 'Invoices' } ]; <TreeViewComponent fields={ { dataSource: dataSource, id: 'id', text: 'name', parentID: 'pid', hasChildren: 'hasChild' } } disabled={true}></TreeViewComponent>

Props: disabled

const dataSource = [ { id: '1', label: 'Documents' }, { id: '2', parentId: '1', label: 'Reports' }, { id: '3', parentId: '1', label: 'Invoices' } ]; <TreeView dataSource={dataSource} disabled={true}></TreeView>

The disabled prop is supported in both EJ2 React and React.

Props: enableRtl

const dataSource = [ { id: '1', name: 'Documents', hasChild: true }, { id: '2', pid: '1', name: 'Reports' }, { id: '3', pid: '1', name: 'Invoices' } ]; <TreeViewComponent fields={ { dataSource: dataSource, id: 'id', text: 'name', parentID: 'pid', hasChildren: 'hasChild' } } enableRtl={true}></TreeViewComponent>

Props: dir

const dataSource = [ { id: '1', label: 'Documents' }, { id: '2', parentId: '1', label: 'Reports' }, { id: '3', parentId: '1', label: 'Invoices' } ]; <Provider dir='rtl'><TreeView dataSource={dataSource}></TreeView></Provider>

The enableRtl property in EJ2 React is replaced with the dir attribute in React, which is applied globally by wrapping the components in a Provider.

Props: expandOn

const dataSource = [ { id: '1', name: 'Documents', hasChild: true }, { id: '2', pid: '1', name: 'Reports' }, { id: '3', pid: '1', name: 'Invoices' } ]; <TreeViewComponent fields={ { dataSource: dataSource, id: 'id', text: 'name', parentID: 'pid', hasChildren: 'hasChild' } } expandOn='Click'></TreeViewComponent>

Props: expandOn

const dataSource = [ { id: '1', label: 'Documents' }, { id: '2', parentId: '1', label: 'Reports' }, { id: '3', parentId: '1', label: 'Invoices' } ]; <TreeView dataSource={dataSource} expandOn='Click'></TreeView>

The expandOn prop is supported in both EJ2 React and React.

Props: expandedNodes

const dataSource = [ { id: '1', name: 'Documents', hasChild: true }, { id: '2', pid: '1', name: 'Reports' }, { id: '3', pid: '1', name: 'Invoices' } ]; <TreeViewComponent fields={ { dataSource: dataSource, id: 'id', text: 'name', parentID: 'pid', hasChildren: 'hasChild' } } expandedNodes={['1']}></TreeViewComponent>

Props: defaultExpandedIds / expandedIds

const dataSource = [ { id: '1', label: 'Documents' }, { id: '2', parentId: '1', label: 'Reports' }, { id: '3', parentId: '1', label: 'Invoices' } ]; <TreeView dataSource={dataSource} defaultExpandedIds={['1']}></TreeView>

The expandedNodes prop in EJ2 React is replaced with the defaultExpandedIds and expandedIds props in React.

Props: fullRowNavigable

const dataSource = [ { id: '1', name: 'Documents', hasChild: true, navigateUrl: '/documents' }, { id: '2', pid: '1', name: 'Reports' }, { id: '3', pid: '1', name: 'Invoices' } ]; <TreeViewComponent fields={ { dataSource: dataSource, id: 'id', text: 'name', parentID: 'pid', hasChildren: 'hasChild', navigateUrl: 'navigateUrl' } } fullRowNavigable={true}></TreeViewComponent>

Props: fullRowNavigable

const dataSource = [ { id: '1', label: 'Documents', navigateUrl: '/documents' }, { id: '2', parentId: '1', label: 'Reports' }, { id: '3', parentId: '1', label: 'Invoices' } ]; <TreeView dataSource={dataSource} fields={ { id: 'id', text: 'label', parentId: 'parentId', navigateUrl: 'navigateUrl' } } fullRowNavigable={true}></TreeView>

The fullRowNavigable prop is supported in both EJ2 React and React.

Props: fullRowSelect

const dataSource = [ { id: '1', name: 'Documents', hasChild: true }, { id: '2', pid: '1', name: 'Reports' }, { id: '3', pid: '1', name: 'Invoices' } ]; <TreeViewComponent fields={ { dataSource: dataSource, id: 'id', text: 'name', parentID: 'pid', hasChildren: 'hasChild' } } fullRowSelect={true}></TreeViewComponent>

Props: fullRowSelect

const dataSource = [ { id: '1', label: 'Documents' }, { id: '2', parentId: '1', label: 'Reports' }, { id: '3', parentId: '1', label: 'Invoices' } ]; <TreeView dataSource={dataSource} fullRowSelect={true}></TreeView>

The fullRowSelect prop is supported in both EJ2 React and React.

Props: height

const dataSource = [ { id: '1', name: 'Documents', hasChild: true }, { id: '2', pid: '1', name: 'Reports' }, { id: '3', pid: '1', name: 'Invoices' } ]; <TreeViewComponent fields={ { dataSource: dataSource, id: 'id', text: 'name', parentID: 'pid', hasChildren: 'hasChild' } } height='500px'></TreeViewComponent>

Props: style

const dataSource = [ { id: '1', label: 'Documents' }, { id: '2', parentId: '1', label: 'Reports' }, { id: '3', parentId: '1', label: 'Invoices' } ]; <TreeView dataSource={dataSource} style={ { height: '500px' } }></TreeView>

The height prop in EJ2 React is replaced with the standard React style prop in React, which accepts the height value through the height CSS property to control the fixed height of the Tree View container.

Props: nodeTemplate

const dataSource = [ { id: '1', name: 'Documents', hasChild: true }, { id: '2', pid: '1', name: 'Reports' }, { id: '3', pid: '1', name: 'Invoices' } ]; const nodeTemplate = (data: any) => { return <div><span className='e-treeview-icon'></span>{data.name}</div>; }; <TreeViewComponent fields={ { dataSource: dataSource, id: 'id', text: 'name', parentID: 'pid', hasChildren: 'hasChild' } } nodeTemplate={nodeTemplate}></TreeViewComponent>

Props: JSX children composition

import { TreeView, TreeViewNodes, TreeViewNode, TreeViewItemLabel } from '@syncfusion/react-navigations'; const data = [ { id: '1', label: 'Documents' }, { id: '2', label: 'Resume.docx' } ]; const fields = { id: 'id', label: 'label' }; <TreeView dataSource={data} fields={fields}> <TreeViewNodes> {(ctx) => ( <TreeViewNode> <TreeViewItemLabel>{String((ctx.item as { label: string }).label)}</TreeViewItemLabel> </TreeViewNode> )} </TreeViewNodes> </TreeView>

The nodeTemplate prop in EJ2 React is replaced with a JSX composite pattern in React. Use the TreeViewNodes, TreeViewNode, TreeViewItemLabel, TreeviewLoadIcon, TreeViewItemToggle, TreeViewItemIcon, TreeViewItemCheckbox, TreeViewEditInput, and TreeViewEmptyState sub-components to render customized content for each node in the Tree View.

Props: query

const dataSource = new DataManager({ url: 'https://example.com/api/items', adaptor: new WebApiAdaptor, crossDomain: true }); const fields = { id: 'id', text: 'name', parentID: 'pid' }; const query = new Query().take(10).requiresCount(); <TreeViewComponent fields={ { dataSource: dataSource, id: 'id', text: 'name', parentID: 'pid' } } query={query}></TreeViewComponent>

Props: query

const dataSource = new DataManager({ url: 'https://example.com/api/items', adaptor: new WebApiAdaptor, crossDomain: true }); const query = new Query().take(10).requiresCount(); <TreeView dataSource={dataSource} query={query}></TreeView>

The query prop is supported in both EJ2 React and React.

Props: selectedNodes / checkedNodes

const dataSource = [ { id: '1', name: 'Documents', hasChild: true }, { id: '2', pid: '1', name: 'Reports' }, { id: '3', pid: '1', name: 'Invoices' } ]; <TreeViewComponent fields={ { dataSource: dataSource, id: 'id', text: 'name', parentID: 'pid', hasChildren: 'hasChild' } } selectedNodes={['2']} checkedNodes={['2']} showCheckBox={true}></TreeViewComponent>

Props: defaultSelectedIds / selectedIds

const dataSource = [ { id: '1', label: 'Documents' }, { id: '2', parentId: '1', label: 'Reports' }, { id: '3', parentId: '1', label: 'Invoices' } ]; <TreeView dataSource={dataSource} defaultSelectedIds={['2']}></TreeView>

The selectedNodes and checkedNodes props in EJ2 React are replaced with the defaultSelectedIds and selectedIds props in React.

Props: showCheckBox

const dataSource = [ { id: '1', name: 'Documents', hasChild: true }, { id: '2', pid: '1', name: 'Reports' }, { id: '3', pid: '1', name: 'Invoices' } ]; <TreeViewComponent fields={ { dataSource: dataSource, id: 'id', text: 'name', parentID: 'pid', hasChildren: 'hasChild' } } showCheckBox={true}></TreeViewComponent>

Props: selectionMode

const dataSource = [ { id: '1', label: 'Documents' }, { id: '2', parentId: '1', label: 'Reports' }, { id: '3', parentId: '1', label: 'Invoices' } ]; <TreeView dataSource={dataSource} selectionMode='Checkbox'></TreeView>

The showCheckBox prop in EJ2 React is replaced with the selectionMode prop set to 'Checkbox' in React.

Props: sortOrder

const dataSource = [ { id: '1', name: 'Documents', hasChild: true }, { id: '2', pid: '1', name: 'Reports' }, { id: '3', pid: '1', name: 'Invoices' } ]; <TreeViewComponent fields={ { dataSource: dataSource, id: 'id', text: 'name', parentID: 'pid', hasChildren: 'hasChild' } } sortOrder='Ascending'></TreeViewComponent>

Props: sortOrder

const dataSource = [ { id: '1', label: 'Documents' }, { id: '2', parentId: '1', label: 'Reports' }, { id: '3', parentId: '1', label: 'Invoices' } ]; <TreeView dataSource={dataSource} sortOrder='SortOrder.Ascending'></TreeView>

The sortOrder prop is supported in both EJ2 React and React.

Events

EJ2 ReactReactDescription

Event: actionFailure

const dataSource = new DataManager({ url: 'https://example.com/api/items', adaptor: new WebApiAdaptor, crossDomain: true }); const handleActionFailure = (args) => { console.log('Action failure:', args.error); }; <TreeViewComponent fields={ { dataSource: dataSource, id: 'id', text: 'name', parentID: 'pid' } } actionFailure={(e) => handleActionFailure(e)}></TreeViewComponent>

Event: onError

const dataSource = new DataManager({ url: 'https://example.com/api/items', adaptor: new WebApiAdaptor, crossDomain: true }); const handleError = (event: Error) => { console.log('Data fetch error:', event); }; <TreeView dataSource={dataSource} onError={(e) => handleError(e)}></TreeView>

The actionFailure event in EJ2 React is replaced with the onError event in React.

Event: keyPress

const dataSource = [ { id: '1', name: 'Documents', hasChild: true }, { id: '2', pid: '1', name: 'Reports' }, { id: '3', pid: '1', name: 'Invoices' } ]; const handleKeyPress = (args) => { console.log('Key pressed on node:', args.node); }; <TreeViewComponent fields={ { dataSource: dataSource, id: 'id', text: 'name', parentID: 'pid', hasChildren: 'hasChild' } } keyPress={(e) => handleKeyPress(e)}></TreeViewComponent>

Event: onKeyPress

const dataSource = [ { id: '1', label: 'Documents' }, { id: '2', parentId: '1', label: 'Reports' }, { id: '3', parentId: '1', label: 'Invoices' } ]; const handleKeyPress = (event) => { console.log('Key pressed on node:', event); }; <TreeView dataSource={dataSource} onKeyPress={(e) => handleKeyPress(e)}></TreeView>

The keyPress event in EJ2 React is replaced with the onKeyPress event in React.

Event: nodeClicked

const dataSource = [ { id: '1', name: 'Documents', hasChild: true }, { id: '2', pid: '1', name: 'Reports' }, { id: '3', pid: '1', name: 'Invoices' } ]; const handleNodeClicked = (args) => { console.log('Node clicked:', args.node); }; <TreeViewComponent fields={ { dataSource: dataSource, id: 'id', text: 'name', parentID: 'pid', hasChildren: 'hasChild' } } nodeClicked={(e) => handleNodeClicked(e)}></TreeViewComponent>

Event: onItemClick

const dataSource = [ { id: '1', label: 'Documents' }, { id: '2', parentId: '1', label: 'Reports' }, { id: '3', parentId: '1', label: 'Invoices' } ]; const handleItemClick = (event) => { console.log('Node clicked:', event); }; <TreeView dataSource={dataSource} onItemClick={(e) => handleItemClick(e)}></TreeView>

The nodeClicked event in EJ2 React is replaced with the onItemClick event in React.

Event: nodeCollapsed / nodeCollapsing / nodeExpanded / nodeExpanding

const dataSource = [ { id: '1', name: 'Documents', hasChild: true }, { id: '2', pid: '1', name: 'Reports' }, { id: '3', pid: '1', name: 'Invoices' } ]; const handleExpanded = (args) => { console.log('Node expanded:', args.node); }; <TreeViewComponent fields={ { dataSource: dataSource, id: 'id', text: 'name', parentID: 'pid', hasChildren: 'hasChild' } } nodeExpanded={(e) => handleExpanded(e)}></TreeViewComponent>

Event: onExpandedChange

const dataSource = [ { id: '1', label: 'Documents' }, { id: '2', parentId: '1', label: 'Reports' }, { id: '3', parentId: '1', label: 'Invoices' } ]; const handleExpandedChange = (event) => { console.log('Expanded set changed:', event); }; <TreeView dataSource={dataSource} onExpandedChange={(e) => handleExpandedChange(e)}></TreeView>

The nodeCollapsed, nodeCollapsing, nodeExpanded, and nodeExpanding events in EJ2 React are replaced with the onExpandedChange event in React.

Event: nodeEdited / nodeEditing

const dataSource = [ { id: '1', name: 'Documents', hasChild: true }, { id: '2', pid: '1', name: 'Reports' }, { id: '3', pid: '1', name: 'Invoices' } ]; const handleNodeEdited = (args) => { console.log('Node edited:', args.node); }; <TreeViewComponent fields={ { dataSource: dataSource, id: 'id', text: 'name', parentID: 'pid', hasChildren: 'hasChild' } } allowEditing={true} nodeEdited={(e) => handleNodeEdited(e)}></TreeViewComponent>

Event: onNodeEdit

const dataSource = [ { id: '1', label: 'Documents' }, { id: '2', parentId: '1', label: 'Reports' }, { id: '3', parentId: '1', label: 'Invoices' } ]; const handleNodeEdit = (event) => { console.log('Node edited:', event); }; <TreeView dataSource={dataSource} editable={true} onNodeEdit={(e) => handleNodeEdit(e)}></TreeView>

The nodeEdited and nodeEditing events in EJ2 React are replaced with the onNodeEdit event in React.

Event: nodeSelected / nodeSelecting / nodeChecked / nodeChecking

const dataSource = [ { id: '1', name: 'Documents', hasChild: true }, { id: '2', pid: '1', name: 'Reports' }, { id: '3', pid: '1', name: 'Invoices' } ]; const handleNodeSelected = (args) => { console.log('Node selected:', args.node); }; const handleNodeChecked = (args) => { console.log('Node checked:', args.node); }; <TreeViewComponent fields={ { dataSource: dataSource, id: 'id', text: 'name', parentID: 'pid', hasChildren: 'hasChild' } } showCheckBox={true} nodeSelected={(e) => handleNodeSelected(e)} nodeChecked={(e) => handleNodeChecked(e)}></TreeViewComponent>

Event: onSelectedChange

const dataSource = [ { id: '1', label: 'Documents' }, { id: '2', parentId: '1', label: 'Reports' }, { id: '3', parentId: '1', label: 'Invoices' } ]; const handleSelectedChange = (event) => { console.log('Selected set changed:', event); }; <TreeView dataSource={dataSource} onSelectedChange={(e) => handleSelectedChange(e)}></TreeView>

The nodeSelected, nodeSelecting, nodeChecked, and nodeChecking events in EJ2 React are replaced with the onSelectedChange event in React.

Methods

EJ2 ReactReactDescription

Methods: expandAll

const dataSource = [ { id: '1', name: 'Documents', hasChild: true }, { id: '2', pid: '1', name: 'Reports' }, { id: '3', pid: '1', name: 'Invoices' } ]; <TreeViewComponent id="tree" fields={ { dataSource: dataSource, id: 'id', text: 'name', parentID: 'pid', hasChildren: 'hasChild' } } ref={(scope) => { treeObj = scope }}></TreeViewComponent> treeObj.expandAll();

Methods: expandAll

const dataSource = [ { id: '1', label: 'Documents' }, { id: '2', parentId: '1', label: 'Reports' }, { id: '3', parentId: '1', label: 'Invoices' } ]; const treeRef = useRef<ITreeView>(null); <TreeView dataSource={dataSource} ref={treeRef}></TreeView> treeRef.current?.expandAll();

The expandAll method is supported in both EJ2 React and React. It expands every loaded node in the Tree View, with an optional ids parameter to expand a subset of root ids in React.

Methods: collapseAll

const dataSource = [ { id: '1', name: 'Documents', hasChild: true }, { id: '2', pid: '1', name: 'Reports' }, { id: '3', pid: '1', name: 'Invoices' } ]; <TreeViewComponent id="tree" fields={ { dataSource: dataSource, id: 'id', text: 'name', parentID: 'pid', hasChildren: 'hasChild' } } ref={(scope) => { treeObj = scope }}></TreeViewComponent> treeObj.collapseAll();

Methods: collapseAll

const dataSource = [ { id: '1', label: 'Documents' }, { id: '2', parentId: '1', label: 'Reports' }, { id: '3', parentId: '1', label: 'Invoices' } ]; const treeRef = useRef<ITreeView>(null); <TreeView dataSource={dataSource} ref={treeRef}></TreeView> treeRef.current?.collapseAll();

The collapseAll method is supported in both EJ2 React and React. It collapses every currently-expanded node in the Tree View, with an optional ids parameter to collapse a subset of root ids in React.