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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/42752187/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 04:20:24  来源:igfitidea点击:

Uncaught TypeError: *** is not a function in a React component

reactjstypescript

提问by Greg Forel

I'm passing an object as an argument in a React component's constructor. Then, I want to call one of the object's function, but get this error message:

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

I read some posts about binding methods to this in the constructor, but as I am calling a function of an object I passed as an argument, I am not sure this applies here, and still got a similar message saying bind is not a function.

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

Here's my code, Wbsis the root React component, WbsLayoutis an object I pass as a parameter to Wbs' constructor.

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

The error happens in the constructor, when I do this.layout.getWbsLayout()Note that I tried to call the function in ComponentDidMountinstead, but got the same error.

错误发生在构造函数中,当我这样做时请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;

Here's WbsLayout:

这是WbsLayout

export class 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;

Here's how I instantiate Wbs:

这是我实例化 Wbs 的方法:

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

let layout: WbsLayout = new WbsLayout(graph);
let wbs = new Wbs(null, layout);

I can see json objects in Wbs' constructor: console.log(layout.cy.elements().jsons());

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

采纳答案by Ben Fletcher

EDIT: Problem turned out to be unrelated, but it's worth remembering that React is very good at throwing early warnings about these kinds of things in that it will 'test' your components and throw errors or warnings if things don't 'look' right, e.g., if props aren't coming in as expected. The early warnings are sometimes so'helpful' that they can throw off your normal debugging instincts.

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



Original answer:

原答案:

Either shield the function call from executing before the props get passed in or set default props setting some kind of dummy or fallback function behavior.

要么在传入 props 之前屏蔽函数调用的执行,要么设置默认 props 设置某种虚拟或回退函数行为。

In the constructor:

在构造函数中:

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

Other options:

其他选项:

  • define a default value for the function.
  • execute the function in componentWillMountor componentDidMount, depending on your needs. Lifecycle hooks are the right place to execute data instantiation. The constructor is best for state and static calls like binding your class's functions, as needed.
  • 定义函数的默认值。
  • 根据您的需要,在componentWillMount或 中执行函数componentDidMount。生命周期钩子是执行数据实例化的正确位置。构造函数最适合状态调用和静态调用,例如根据需要绑定类的函数。