mui-x icon indicating copy to clipboard operation
mui-x copied to clipboard

[TreeView] Do not re-render every Tree Item when the Rich Tree View re-renders (introduce selectors)

Open flaviendelangle opened this issue 1 year ago • 17 comments

Part of #14200

Work

Internal changes

  • [x] Rename itemMetaMap => itemMetaLookup to make clear it is an object and not a Map (now that we do have map in the state)
  • [x] Rename itemMap => itemModelLookup to make clear it is an object and not a Map (now that we do have map in the state) and to be more precise about what it contains
  • [x] Rename itemOrderedChildrenIds => itemOrderedChildrenIdsLookup to make its purpose more clear
  • [x] Rename itemChildrenIndexes => itemChildrenIndexesLookup to make its purpose more clear
  • [x] Move disabledItemsFocusable to the state instead of passing it to the contextValue, it allows dropping instance.isItemNavigable in favor of a selector
  • [x] Move the focus state in a focus key for consistency
  • [x] Move the label editing state in a label key for consistency
  • [x] Store the selectedItemsMap in the state to be usable in selectors
  • [x] Store the expandedItemsMap in the state to be usable in selectors
  • [x] Store the defaultFocusableItemId in the state to be usable in selectors

Introduce selectors

  • [x] Replace the state with a store stored in a ref

    // Access
    -const itemsReordering = state.itemsReordering;
    +const itemsReordering = store.value.itemsReordering; // without selectors (should not do it);
    +const itemsReordering = selectorItemsReordering(store.value); // with selectors
    
    // Updates
    -setState((prevState) => ({ ...prevState, itemsReordering: null }));
    +store.update((prevState) => ({ ...prevState, itemsReordering: null }));
    
  • [x] Create selectors for every state access

    The selectors are defined by each plugin in a useTreeViewXXX.selectors.ts file:

    // Each plugin has a root selector that returns its entire state.
    // This selector is not exported by the file
    const selectorTreeViewItemsState: TreeViewRootSelector<UseTreeViewItemsSignature> = (state) =>
    state.items;
    
    // The plugin then defines selectors using `createSelectors` 
    const selectorItemMetaLookup = createSelector(
      selectorTreeViewItemsState,
      (items) => items.itemMetaLookup,
    );
    
    // Those selectors can also accept additional arguments
    const selectorItemOrderedChildrenIds = createSelector(
      [selectorTreeViewItemsState, (_, itemId: string | null) => itemId],
      (itemsState, itemId) =>
        itemsState.itemOrderedChildrenIdsLookup[itemId ?? TREE_VIEW_ROOT_PARENT_ID] ?? EMPTY_CHILDREN,
    );
    
  • [x] Replace every instance call in the render with selectors

    // For selectors without additional parameters
    const itemMetaLookup = useSelector(store, selectorItemMetaLookup);
    
    // For selectors with additional parameters
    -const isExpanded = instance.isItemExpanded(itemId);
    +const isExpanded = useSelector(store, selectorIsItemExpanded, itemId);
    
  • [x] BREAKING: Add idAttribute to TreeItemProviderProps (to stop getting it from itemMeta, see https://github.com/mui/mui-x/pull/14210#discussion_r1815198146 for context)

Add memoization

  • [x] BREAKING: Add React.memo around the WrappedTreeItem component in RichTreeViewItems
  • [x] Make sure every Tree Item do not re-render every time the Tree View re-renders (even when it has children)
  • [x] Add tests

Docs

  • [x] Update the doc examples to not use publicAPI in the render

Extracted PRs

  • #14661
  • #14665
  • #14667
  • #14749

flaviendelangle avatar Aug 14 '24 15:08 flaviendelangle

This pull request has conflicts, please resolve those before we can evaluate the pull request.

github-actions[bot] avatar Sep 02 '24 14:09 github-actions[bot]

This pull request has conflicts, please resolve those before we can evaluate the pull request.

github-actions[bot] avatar Sep 19 '24 11:09 github-actions[bot]

This pull request has conflicts, please resolve those before we can evaluate the pull request.

github-actions[bot] avatar Sep 25 '24 08:09 github-actions[bot]

This pull request has conflicts, please resolve those before we can evaluate the pull request.

github-actions[bot] avatar Sep 25 '24 14:09 github-actions[bot]

This pull request has conflicts, please resolve those before we can evaluate the pull request.

github-actions[bot] avatar Sep 25 '24 14:09 github-actions[bot]

This pull request has conflicts, please resolve those before we can evaluate the pull request.

github-actions[bot] avatar Sep 26 '24 11:09 github-actions[bot]

This pull request has conflicts, please resolve those before we can evaluate the pull request.

github-actions[bot] avatar Sep 30 '24 10:09 github-actions[bot]

This pull request has conflicts, please resolve those before we can evaluate the pull request.

github-actions[bot] avatar Oct 01 '24 12:10 github-actions[bot]

This pull request has conflicts, please resolve those before we can evaluate the pull request.

github-actions[bot] avatar Oct 08 '24 10:10 github-actions[bot]

This pull request has conflicts, please resolve those before we can evaluate the pull request.

github-actions[bot] avatar Oct 14 '24 12:10 github-actions[bot]

This pull request has conflicts, please resolve those before we can evaluate the pull request.

github-actions[bot] avatar Oct 17 '24 13:10 github-actions[bot]

This pull request has conflicts, please resolve those before we can evaluate the pull request.

github-actions[bot] avatar Oct 21 '24 10:10 github-actions[bot]

This pull request has conflicts, please resolve those before we can evaluate the pull request.

github-actions[bot] avatar Oct 23 '24 07:10 github-actions[bot]

This pull request has conflicts, please resolve those before we can evaluate the pull request.

github-actions[bot] avatar Oct 23 '24 13:10 github-actions[bot]

@noraleonte I'm opening for review mostly so we can start discussing the DX and the impact on the doc We are still missing lots of tests plus the migration guide.

flaviendelangle avatar Oct 24 '24 15:10 flaviendelangle

This pull request has conflicts, please resolve those before we can evaluate the pull request.

github-actions[bot] avatar Oct 31 '24 14:10 github-actions[bot]

This pull request has conflicts, please resolve those before we can evaluate the pull request.

github-actions[bot] avatar Nov 07 '24 08:11 github-actions[bot]

This pull request has conflicts, please resolve those before we can evaluate the pull request.

github-actions[bot] avatar Nov 07 '24 11:11 github-actions[bot]