Я пытаюсь измерить позицию DOM TreeNodes
. Я использую компонент Ant Design Tree
(я изменил CSS для отображения в виде диаграммы Org).
Мера, кажется, всегда является предыдущей, а не текущей.
Единственная правильная позиция - это первый раз, когда дерево отображается.
Вот репозиторий , чтобы увидеть его в действии:
- Сначала нажмите, чтобы свернуть дерево
- Затем нажмите на первый узел. Вы увидите реальное обновление координат.
Я последовал useCallback
примеру из документа Реакта.
Я пробовал много разных опций в качестве второго аргумента array
внутри моей useLayoutEffect
функции. Единственный, кто обновляет координаты, пропускает второй аргумент, но за счет бесконечного цикла .
import * as React from "react";
import { useCallback, useLayoutEffect, useState } from "react";
export interface TreeNodeProps {
id: string;
nodeData: any;
coordinates?: ClientRect;
}
export const TreeNode: React.FC<TreeNodeProps> = props => {
const { id, nodeData } = props;
const [domElement, setDomElement] = useState<HTMLElement>(undefined);
const [coordinates, setCoordinates] = useState<ClientRect>({
left: 0,
right: 0,
bottom: 0,
top: 0,
height: 0,
width: 0
});
const nodeRef = useCallback((node: HTMLElement) => {
if (node !== null) {
setDomElement(node);
setCoordinates(node.getBoundingClientRect());
}
}, []);
// I tried many combinations for the second argument here
// the only one that always update is no argument at all so the hook
// runs in an infinite loop.
useLayoutEffect(() => {
domElement &&
setCoordinates(roundDecimals(domElement.getBoundingClientRect()));
console.log(props.nodeData.title, JSON.stringify(coordinates, null, 2));
}, [
domElement,
domElement && domElement.getBoundingClientRect().left,
domElement && domElement.getBoundingClientRect().bottom,
domElement && domElement.getBoundingClientRect().right
]);
const wbsId = (nodeData && nodeData.wbsId) || "wbsId";
const title = (nodeData && nodeData.title) || "title";
return (
<div ref={nodeRef} id={id} className={styles.treeNode}>
<p style={{ margin: 0 }}>
{wbsId} {title}
</p>
<div style={{ display: "inline-flex" }}>
<ul style={{ margin: 0 }}>
<li>left: {coordinates.left}</li>
<li>right: {coordinates.right}</li>
</ul>
<ul style={{ margin: 0 }}>
<li>bottom: {coordinates.bottom}</li>
<li>top: {coordinates.top}</li>
</ul>
<ul style={{ margin: 0 }}>
<li>height: {coordinates.height}</li>
<li>width: {coordinates.width}</li>
</ul>
</div>
</div>
);
};