javascript - 弹出框没有出现在 React 中

标签 javascript html reactjs popover

我正在尝试使用 Treeviz 依赖项制作 Web 应用程序。目标是在树的每个节点上放置一个弹出按钮,如果用户单击按钮,他/她可以看到节点的描述,之后它应该是可编辑的。我尝试了很多方法,但对我来说 popover 在 React 中不起作用。
有一个我想做的例子。您可以看到我必须将 React 组件插入 HTML,因此我使用的是 renderToString。您只需要查看树的 renderNode 属性。我在 renderNode 中引用 React 组件,例如:${tooltip} ${popover}。

import React from "react";
import { TreevizReact } from "treeviz-react";
import { renderToString } from "react-dom/server";
const data_1 = [
  {
    id: 1,
    text_1: "Chaos",
    description: "Void",
    father: null,
    color: "#FF5722"
  },
  {
    id: 2,
    text_1: "Tartarus",
    description: "Abyss",
    father: 1,
    color: "#FFC107"
  },
  { id: 3, text_1: "Gaia", description: "Earth", father: 1, color: "#8BC34A" },
  { id: 4, text_1: "Eros", description: "Desire", father: 1, color: "#00BCD4" }
];

export const App = () => {
  return (
    <div style={{ marginLeft: 10 }}>
      <div style={{ display: "flex" }}>
        <TreevizReact
          data={data_1}
          relationnalField={"father"}
          nodeWidth={120}
          nodeHeight={80}
          areaHeight={500}
          areaWidth={1000}
          mainAxisNodeSpacing={2}
          secondaryAxisNodeSpacing={2}
          linkShape={"quadraticBeziers"}
          renderNode={(data) => {
            const nodeData = data.data;
            const settings = data.settings;
            let result = "";
            const tooltip = renderToString(
              <strong
                data-toggle="tooltip"
                data-placement="top"
                title={nodeData.description}
              >
                {nodeData.text_1}
              </strong>
            );
            const popover = renderToString(
              <button
                type="button"
                className="btn btn-secondary"
                data-container="body"
                data-toggle="popover"
                data-placement="top"
                data-content={nodeData.description}
              >
                Popover on top
              </button>
            );
            if (data.depth !== 2) {
              result = `<div className="box" 
              style='cursor:pointer;height:${settings.nodeHeight}px; width:${settings.nodeWidth}px;display:flex;flex-direction:column;justify-content:center;align-items:center;background-color:${nodeData.color};border-radius:5px;'>
              <div>
          ${tooltip}
          ${popover}
          </div></div>`;
            } else {
              result = `<div className="box" style='cursor:pointer;height:${
                settings.nodeHeight
              }px; width:${
                settings.nodeHeight
              }px;display:flex;flex-direction:column;justify-content:center;align-items:center;background-color:${
                nodeData.color
              };border-radius:${settings.nodeHeight / 2}px;'><div><strong>
          ${nodeData.text_1}
          </strong></div></div>`;
            }
            return result;
          }}
          duration={600}
          isHorizontal
          linkWidth={(node) => 10}
        />
      </div>
    </div>
  );
};
export default App;

工具提示正在工作,但弹出框未显示。
enter image description here
你可以试试:https://codesandbox.io/s/zealous-orla-4bq5f?file=/src/App.js
也试过
const popover = renderToString(
              <Popup
                trigger={<button> Trigger</button>}
                position="right center"
              >
                <form onSubmit={saveHandler}>
                  <ContentEditable
                    html={text.current}
                    onChange={handleChange}
                  />
                  <button type="submit">Save</button>
                  <button>Cancel</button>
                </form>
              </Popup>
const popoverContent = (
              <Popover id="popover-basic">
                <Popover.Header as="h3">Popover right</Popover.Header>
                <Popover.Body>
                  And here's some <strong>amazing</strong> content. It's very
                  engaging. right?
                </Popover.Body>
              </Popover>
            );

            const popover = renderToString(
              <OverlayTrigger
                trigger="click"
                placement="right"
                overlay={popoverContent}
              >
                <Button variant="success">Click me to see</Button>
              </OverlayTrigger>
            );
他们都没有为我工作。

最佳答案

可能您的方法不起作用,因为树中的 dom 元素是动态创建的,并且 bootstrap doesn't set them up .
一种更具 react 性的方法是使用 react-bootstrap 库并管理状态中的每个 UI 方面。要实现工具提示,Overlay组件实际上是一个名为 target 的 Prop ,它允许您更改显示工具提示的元素。

    <Overlay target={tooltipTarget} show={showTooltip} placement="right">
      {(props) => (
        <Tooltip id="overlay-example" {...props}>
          {tooltipNode?.data.text_1}
        </Tooltip>
      )}
    </Overlay>
那么您只需要在onNodeMouseEnter 中管理所有这些状态即可。和 onNodeMouseLeave TreevizReact 中的处理程序零件。
        onNodeMouseEnter={(_event, node) => {
          const t = document.querySelector(`#node-${node.id}`);
          setTooltipTarget(t);
          setShowTooltip(true);
          setTooltipNode(node);
        }}
        onNodeMouseLeave={(_event, node) => {
          setTooltipTarget(null);
          setShowTooltip(false);
          setTooltipNode(null);
        }}
弹出窗口遵循与另一组状态相同的逻辑。
  <div ref={ref}>
    <Overlay
      show={!!selectedNode.current}
      target={target}
      placement="bottom"
      container={ref.current}
      containerPadding={20}
    >
      <Popover id="popover-contained">
        {/* hack to avoid weird blinking (due mutable state) */}
        {!!selectedNode.current && (
          <>
            some form based on node data
            {JSON.stringify(selectedNode.current?.data)}
          </>
        )}
      </Popover>
    </Overlay>
  </div>
在 onNodeClick 处理程序中
        onNodeClick={(_event, node) => {
          const t = document.querySelector(`#node-${node.id}`);
          // unselect if already selected
          if (selectedNode.current?.id === node.id) {
            selectedNode.current = null;
            setTarget(null);
          } else {
            selectedNode.current = node;
            setTarget(t);
          }
        }}
您可能会注意到这次我通过 ref (selectedNode.current) 使用了一个可变变量,由于某种原因,使用 state 导致了一些问题,可能是由于 D3 和 react 具有不同的渲染周期,因此您可能会遇到一些其他故障在这个实现中。
https://codesandbox.io/s/quizzical-buck-slofh?file=/src/App.js

关于javascript - 弹出框没有出现在 React 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69206761/

相关文章:

javascript - 如何在 $(document).ready 函数中添加多个函数

javascript - 与 Node 异步不是更好吗

javascript - 在 Javascript 中创建按钮

java - Jsoup对特定表数据的处理

html - 使 div 垂直跨越所有可用高度

javascript - 在 react 中从同一文件导入多个组件而不是导入每个组件的正确方法是什么

javascript - React JSX 中的 ...rest 是什么意思?

javascript - js对象实例的区别

javascript - 单击图像以打开带有静态文本的幻灯片

javascript - 如何在 React Router 中获取多个字符串参数