未捕获的类型错误:*** 不是 React 组件中的函数

Gre*_*rel 6 typescript reactjs

我在 React 组件的构造函数中传递一个对象作为参数。然后,我想调用对象的函数之一,但收到此错误消息:

Uncaught TypeError: _this.layout.getWbsLayout is not a function
    at new Wbs (Wbs.tsx:50)
    at react-dom.js:4749
    at measureLifeCyclePerf (react-dom.js:4529)
    at ReactCompositeComponentWrapper._constructComponentWithoutOwner (react-dom.js:4748)
    at ReactCompositeComponentWrapper._constructComponent (react-dom.js:4734)
    at ReactCompositeComponentWrapper.mountComponent (react-dom.js:4642)
    at Object.mountComponent (react-dom.js:11542)
    at ReactCompositeComponentWrapper.performInitialMount (react-dom.js:4825)
    at ReactCompositeComponentWrapper.mountComponent (react-dom.js:4712)
    at Object.mountComponent (react-dom.js:11542)
Run Code Online (Sandbox Code Playgroud)

我在构造函数中阅读了一些关于将方法绑定到 this 的帖子,但是当我调用作为参数传递的对象的函数时,我不确定这是否适用于此,并且仍然收到类似的消息说bind is not a function.

这是我的代码,Wbs是根 React 组件,WbsLayout是我作为参数传递给 Wbs 的构造函数的对象。

错误发生在构造函数中,当我这样做时请this.layout.getWbsLayout() 注意,我尝试在其中调用该函数ComponentDidMount,但遇到了相同的错误。

import * as React from 'react';
import WbsLayout from "../layout/WbsLayout";

interface WbsProps {}
interface WbsState {
    wbsElements: any[];
    wbsEdges: any[]
}

class Wbs extends React.Component<WbsProps, WbsState>{

    public cy: Cy.Instance;
    private layout: WbsLayout;
    private s: snap.Paper;
    private renderer: WbsRenderer;

    public state : WbsState;

    constructor(props: WbsProps, layout: WbsLayout) {
        super(props);
        this.layout = layout;
        this.cy = this.layout.cy;

        // this does show a json object in the console, hence layout can be accessed
        console.log(layout.cy.elements().jsons());

        this.layout.getWbsLayout(); //The error happens here

        // initial state
        this.state = {
            wbsElements: [],
            wbsEdges: [],
        };
    }

    public render() {

        const wbsElements: any = this.state.wbsElements.map((element: any) => (
            <WbsElement
                key={element.wbsElementBox.nodeId}
                wbsElementBox={...element.wbsElementBox}
                wbsElementTitle={...element.wbsElementTitle}
                wbsElementId={...element.wbsElementId}
            />
        ));

        const wbsEdges: any = this.state.wbsEdges.map((edge: any) => (
            <WbsEdge
                key={edge.edgeId}
                edgeId={edge.edgeId}
                sourceWbsElementData={...edge.sourceWbsElementData}
                targetWbsElementData={...edge.targetWbsElementData}
            />
        ));

        return (
            <svg>
                {wbsElements}
                {wbsEdges}
            </svg>
        );
    }
}

export default Wbs;
Run Code Online (Sandbox Code Playgroud)

这是WbsLayout

导出类 WbsLayout {

    public cy: Cy.Instance;

    constructor(graph: any, Options?: Options) {

        this.cy = cytoscape({
            headless: true,
            elements: graph
        });

    }

    public getWbsLayout(): any {
        const wbsElements: any = this.cy.collection("node[visibility = 'visible']").map((n: Cy.CollectionNodes) =>
            ({
                wbsElementBox: {
                    nodeId: n.data().id,
                    x: n.data().x,
                    y: n.data().y,
                    width: n.data().width,
                    height: n.data().height
                },
                wbsElementTitle: {
                    text: n.data().title
                },
                wbsElementId: {
                    text: n.data().wbsId
                }
            })
        );

        const wbsEdges: any = [
            {
                edgeId: '5',
                sourceWbsElementData: {
                    nodeId: '1',
                    x:464.359375,
                    y:30,
                    width:100,
                    height:40,
                    layoutStyle: 0
                },
                targetWbsElementData: {
                    nodeId:'1.5',
                    x:867.875,
                    y:100,
                    width:130.84375,
                    height:40,
                    layoutStyle: 1
                }

            }
        ];

        return {
            wbsElements,
            wbsEdges
        };
    }

    ....
}
export default WbsLayout;
Run Code Online (Sandbox Code Playgroud)

这是我实例化 Wbs 的方法:

let graph: any = {
    nodes: [],
    edges: []
};

let layout: WbsLayout = new WbsLayout(graph);
let wbs = new Wbs(null, layout);
Run Code Online (Sandbox Code Playgroud)

我可以在 Wbs 的构造函数中看到 json 对象:console.log(layout.cy.elements().jsons());

Ben*_*her 1

编辑:问题结果是无关的,但值得记住的是,React 非常擅长针对此类事情发出早期警告,因为它会“测试”您的组件,并在事情“看起来”不正确时抛出错误或警告,例如,如果道具没有按预期进入。早期警告有时是如此“有帮助”,以至于它们可能会打乱您正常的调试本能。


原答案:

要么在传入 props 之前阻止函数调用执行,要么设置默认 props 设置某种虚拟或后备函数行为。

在构造函数中:

if (this.layout.getWbsLayout) {
  this.layout.getWbsLayout();
}
Run Code Online (Sandbox Code Playgroud)

其他选项:

  • 定义函数的默认值。
  • 根据您的需要执行componentWillMount或中的函数。componentDidMount生命周期挂钩是执行数据实例化的正确位置。构造函数最适合状态和静态调用,例如根据需要绑定类的函数。