为什么我无法访问自定义 Autodesk 扩展中按钮的 onClick 函数内的 React Context 变量和状态更改?

问题描述 投票:0回答:1

我有一个使用上下文变量并且工作正常的查看器组件。我想为此查看器实现一些自定义扩展,我将它们的声明放在 useEffect 挂钩中,仅运行一次,它们就被注册了。

在这些扩展中,我有一些按钮,它们在

onToolbarCreated
中加载,并且onClick函数使用React Context变量,但它们返回未定义或初始值,如何让它们识别这些变量?

代码:

function Viewer() {
const {
    setMainViewer,
    isTreeActive,
    isIssuesListActive,
    isBlueprintsListActive,
    isIssueDatailsActive,
    setCurrentIssueSelected,
    currentIssueSelected,
} = useContext(AppContext);

useEffect(() => {
    const auxinitViewer = async () => {
        setMainViewer(
            await initViewer(document.getElementById("mainViewerDiv"))
        );
    };
    initExtensions();
    auxinitViewer();
}, []);

const initExtensions = async () => {

    // TOOLBAR EXTENSION
    function UpperViewPanel(viewer, options) {
        //... code
    }

    UpperViewPanel.prototype = Object.create(
        Autodesk.Viewing.UI.DockingPanel.prototype
    );
    UpperViewPanel.prototype.constructor = UpperViewPanel;

    function ToolbarExtension(viewer, options) {
        Autodesk.Viewing.Extension.call(this, viewer, options);
    }

    ToolbarExtension.prototype = Object.create(
        Autodesk.Viewing.Extension.prototype
    );
    ToolbarExtension.prototype.constructor = ToolbarExtension;

    ToolbarExtension.prototype.load = function () {
        this.viewer.fitToView();
        return true;
    };

    ToolbarExtension.prototype.unload = function () {
        if (this.subToolbar) {
            this.viewer.toolbar.removeControl(this.subToolbar);
            this.subToolbar = null;
        }
    };
    var button3 = new Autodesk.Viewing.UI.Button("enable-upper-view");

    ToolbarExtension.prototype.onToolbarCreated = async function (toolbar) {
        var mainViewer = this.viewer;
        const upper_view_panel_div =
            document.getElementById("upper-view-panel");
        if (upper_view_panel_div) {
            upper_view_panel_div.remove();
        }
        
        let panel;
        if (mainViewer.model.is3d()) {
            panel = new UpperViewPanel(this.viewer, null);
            panel.initViewer();
        }

        button3.onClick = function (e) {
            // HERE IS THE PROBLEM, currentIssueSelected is always undefined
            console.log("CURRENT ISSUE SELECTED", currentIssueSelected);
            if (!currentIssueSelected) {
                showErrorToasty(
                    "Não é possível ver planta sem um problema selecionado"
                );
            } else {
                if (!currentIssueSelected.linkedDocuments[0]) {
                    showErrorToasty(
                        "Este problema não contém posicionamento"
                    );
                } else {
                    if (
                        panel.getVisibility().display === "block" &&
                        panel.getVisibility().zIndex === "-1"
                    ) {
                        panel.setIssue(currentIssueSelected);
                        panel.setVisible();
                        button3.removeClass("top_view");
                        button3.addClass("top_view_selected");
                    } else if (panel.getVisibility().display === "none") {
                        panel.setIssue(currentIssueSelected);
                        panel.setVisible();
                        button3.removeClass("top_view");
                        button3.addClass("top_view_selected");
                    } else if (
                        panel.getVisibility().display === "block" &&
                        panel.getVisibility().zIndex === "0"
                    ) {
                        panel.setIssue(currentIssueSelected);
                    }
                }
            }
        };
        button3.removeClass("top_view_selected");
        button3.addClass("top_view");
        button3.setToolTip("Mostrar planta");

        var issues_combo_button = new Autodesk.Viewing.UI.ComboButton(
            "issues_combo_button"
        );
        issues_combo_button.setIcon("issues_combo_button");

        issues_combo_button.onMouseOver = function (e) {
            issues_combo_button.setIcon("issues_combo_button_selected");
        };
        issues_combo_button.onMouseOut = function (e) {
            issues_combo_button.setIcon("issues_combo_button");
        };
        var utils_combo_button = new Autodesk.Viewing.UI.ComboButton(
            "utils_combo_button"
        );
        utils_combo_button.setIcon("utils_combo_button");

        utils_combo_button.onMouseOver = function (e) {
            utils_combo_button.setIcon("utils_combo_button_selected");
        };
        utils_combo_button.onMouseOut = function (e) {
            utils_combo_button.setIcon("utils_combo_button");
        };

        this.subToolbar = new Autodesk.Viewing.UI.ControlGroup(
            "my-custom-toolbar"
        );
        this.subToolbar2 = new Autodesk.Viewing.UI.ControlGroup(
            "my-custom-toolbar2"
        );
        if (mainViewer.model.is3d()) {
            utils_combo_button.addControl(button3);
        }
        this.subToolbar.addControl(issues_combo_button);
        // SubToolbar
        toolbar.addControl(this.subToolbar);
        if (mainViewer.model.is3d()) {
            this.subToolbar2.addControl(utils_combo_button);
            toolbar.addControl(this.subToolbar2);
        }
    };

    Autodesk.Viewing.theExtensionManager.registerExtension(
        "ToolbarExtension",
        ToolbarExtension
    );
};

const handleViewerWidth = () => {
    //...
};

return (
    <div
        style={{
            width: handleViewerWidth(),
            height: "100%",
            position: "absolute",
            left: `${
                isTreeActive || isIssuesListActive || isBlueprintsListActive
                    ? "23%"
                    : "3%"
            }`,
        }}
        id="mainViewerDiv"
    />
)}

在上面的示例中,您可以看到我在button3 onClick 中使用了上下文变量

currentIssueSelected
,但它始终是未定义的,我已经尝试过:

  1. 通过查看器组件函数中的 props 接收 currentIssueValue
    Viewer({currentIssueSel}){...}
    ;
  2. 制作一个全局函数,并赋值给onClick;

有什么建议吗?

javascript reactjs autodesk-forge react-context autodesk-viewer
1个回答
1
投票

这个问题可能与 onClick 函数定义和执行的时间有关,因此您可以尝试使用 useEffect 钩子在上下文值发生变化时更新 onClick 函数。useEffect 及其依赖数组中带有 currentIssueSelected 可以确保每当 currentIssueSelected 发生变化时,onClick 函数就会更新。

 const [button3ClickHandler, setButton3ClickHandler] = useState(() => {});

  useEffect(() => {
    setButton3ClickHandler(() => {
      return function (e) {
        console.log("CURRENT ISSUE SELECTED", currentIssueSelected);
        if (!currentIssueSelected) {
          showErrorToasty(
            "Não é possível ver planta sem um problema selecionado"
          );
        } else {
          // ... rest of your onClick logic ...
        }
      };
    });
  }, [currentIssueSelected]);

  useEffect(() => {
    const auxinitViewer = async () => {
      setMainViewer(await initViewer(document.getElementById("mainViewerDiv")));
    };
    initExtensions();
    auxinitViewer();
  }, [currentIssueSelected]);

  const initExtensions = async () => {
    // ... your existing code ...

    button3.onClick = button3ClickHandler;

    // ... rest of your onToolbarCreated logic ...
  };
© www.soinside.com 2019 - 2024. All rights reserved.