reactjs 使用分支组件时React MUI TreeView键导航中断

ymdaylpp  于 2023-06-05  发布在  React
关注(0)|答案(1)|浏览(172)

当我执行以下操作时,我可以使用箭头键在树中导航,当我在文档中切换时,树会获得焦点(只有根项目,子分支会被打断,因为它们使用了Branch):

const Item = React.memo(function Item({ item }) {
  const { onChange } = useContext(DataContext);
  return (
    <TreeItem
      key={item.key}
      nodeId={item.key}
      label={item.name}
    >
      {Boolean(item?.children) && (
        <Branch data={item.children} />
      )}
    </TreeItem>
  );
});


<TreeView multiSelect selected={NONE}>
  {data
    .map((item) => (
      <Item
        key={item.key}
        item={item}
        nodeId={item.key}
      />
    ))}
</TreeView>

但是当我执行以下操作时,在文档中使用Tab键时,树不会聚焦,并且上下箭头不会在树中导航(仅在单击树中的项目后向左和向右):

<TreeView multiSelect selected={NONE}>
  <Branch data={data} />
</TreeView>

我认为这与不转发引用有关,我尝试了类组件(React.PureComponent),但没有改变。我认为TreeItemTreeView的直接子节点需要有一个nodeId属性,但是对于一组节点来说,它会是什么呢?
一个例子显示了这一工作,但我不能传递nodeId到分支,因为它收到多个。另一个例子展示了使用renderTree函数,但我的项目有一个复选框,选中一个项目会导致整个树重新绘制。
如果我需要转发一个引用,那么它是什么,没有给出这方面的例子吗?

更新

我稍微深入了一下,注意到传递nodeId会破坏它:

const Item = React.memo(function Item({ parent }) {
  const { map } = useContext(DataContext);
  const parentItem = map.get(parent);
  const children = !parentItem?.children
    ? null
    : parentItem.children.map((key) => (
        <Item key={key} parent={key} nodeId={key} />
      ));
  //this will not render root but crashes when Tree passes
  //  a nodeId
  if (!parentItem.parent) {
    return children;
  }
  return (
    <TreeItem
      key={parentItem.key}
      nodeId={parentItem.key}
      label={parentItem.name || "root"}
    >
      {children}
    </TreeItem>
  );
});
const Tree = React.memo(function Tree({ parent }) {
  return (
    <TreeView
      multiSelect
      selected={NONE}
      defaultCollapseIcon={<ExpandMoreIcon />}
      defaultExpandIcon={<ChevronRightIcon />}
    >
      {/* if item does not render parent and I pass nodeId
        it will crash if no nodeId is passed then key
        navigation is broken again */}
      <Item parent={parent} nodeId={parent} />
    </TreeView>
  );
});

如果我传递nodeId但不传递render root,则错误为:
未捕获的类型错误:无法读取buildVisible(TreeView.js:590)中未定义的属性“children”
<ForwardRef(TreeView)>组件中出现上述错误:
传递nodeId并渲染root可以工作,但是root是一个虚拟的,可以使递归更容易,所以我不想渲染它。

gv8xihay

gv8xihay1#

如果我让Item在当前父节点是root时呈现TreeView(root被忽略),那么它工作得很好,下面是代码:

const Item = React.memo(function Item({ parent }) {
  const { map } = useContext(DataContext);
  const parentItem = map.get(parent);
  const children = !parentItem?.children
    ? null
    : parentItem.children.map((key) => (
        <Item key={key} parent={key} nodeId={key} />
      ));
  if (!parentItem.parent) {
    return (
      <TreeView
        multiSelect
        selected={NONE}
        defaultCollapseIcon={<ExpandMoreIcon />}
        defaultExpandIcon={<ChevronRightIcon />}
      >
        {children}
      </TreeView>
    );
  }
  return (
    <TreeItem
      key={parentItem.key}
      nodeId={parentItem.key}
      label={parentItem.name || "root"}
    >
      {children}
    </TreeItem>
  );
});
const Container = React.memo(function Container({
  data,
  values,
}) {
  //code creating a map in context to update on click
  //  and call parent onChange, when there is a change
  //  reRender is set again (parent is a string to parent key)
  return (
    <DataContext.Provider value={contextValue}>
      <Item reRender={reRender} parent={root(map).key} />
    </DataContext.Provider>
  );
});

相关问题