未捕获的TypeError:***不是React组件中的函数

时间:2017-03-12 19:41:04

标签: reactjs typescript

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

我在构造函数中读了一些关于绑定方法的帖子,但是当我调用一个作为参数传递的对象的函数时,我不确定这是否适用于此,并且仍然有类似的消息说{{1 }}

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

当我执行WbsLayout时,错误发生在构造函数中 请注意,我尝试在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;

导出类WbsLayout {

WbsLayout

以下是我实例化Wbs的方法:

    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;

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

2 个答案:

答案 0 :(得分:1)

编辑:问题被证明是无关紧要的,但值得记住的是,React非常擅长对这些事情发出预警,因为它会测试&#39;如果事情不是“看起来”,那么你的组件会抛出错误或警告。是的,例如,如果道具没有按预期进入。早期警告有时所以&#39;有用&#39;他们可以抛弃你正常的调试本能。

原始答案:

要么在传递道具之前屏蔽函数调用,要么设置默认道具设置某种虚拟或回退函数行为。

在构造函数中:

if (this.layout.getWbsLayout) {
  this.layout.getWbsLayout();
}

其他选择:

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

答案 1 :(得分:0)

谢谢大家。第一个提示是正确的:我认为我成功地将布局传递给了wbs构造函数,但我不是。 我重构了我的代码以在道具中包含布局,现在它可以工作。