发出使用React钩子更新DOM元素度量的问题

时间:2019-05-15 00:19:13

标签: reactjs react-hooks

我正在尝试测量TreeNodes的DOM位置。我正在使用Ant Design的Tree组件(我将CSS修改为显示为组织图)。

该指标似乎始终是前一个指标,而不是当前指标。 唯一正确的位置是第一次渲染树。

这里是repository,可以看到它的运行情况:

  • 首先,单击以折叠树
  • 然后单击第一个节点。您会看到真实的坐标更新。

我遵循了React文档中的useCallback example

我在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>
  );
};

0 个答案:

没有答案