• React报错之JSX element type does not have any construct or call signatures


    正文从这开始~

    总览

    当我们试图将元素或react组件作为属性传递给另一个组件,但是属性的类型声明错误时,会产生"JSX element type does not have any construct or call signatures"错误。为了解决该错误,可以使用React.ElementType类型。

    jsx-element-does-not-have-any-construct-or-call-signatures.png

    这里有个例子来展示错误是如何发生的。

    // App.tsx
    import React from 'react';
    
    interface Props {
      comp: JSX.Element;
    }
    
    const Wrapper: React.FunctionComponent<Props> = props => {
      const {comp: Comp} = props;
      // ⛔️ JSX element type 'Comp' does not have any construct or call signatures.ts(2604)
      return (
        <div>
          <Comp name="James" />
        div>
      );
    };
    
    const App: React.FunctionComponent = () => {
      const heading = ({name}: {name: string}) => <h2>Hello {name}h2>;
    
      return (
        <div>
          <Wrapper comp={heading} />
        div>
      );
    };
    
    export default App;
    

    我们尝试将一个React组件作为属性传递给Wrapper组件,但我们将该React组件的类型声明为JSX.Element

    React.ElementType

    为了解决该错误,将属性的类型声明为React.ElementType

    // App.tsx
    import React from 'react';
    
    interface Props {
      comp: React.ElementType; // 👈️ type it as React.ElementType
    }
    
    const Wrapper: React.FunctionComponent<Props> = props => {
      // 👇️ component names must start with capital letter
      const {comp: Comp} = props;
      return (
        <div>
          <Comp name="James" />
        div>
      );
    };
    
    const App: React.FunctionComponent = () => {
      // 👇️ takes a name prop
      const heading = ({name}: {name: string}) => <h2>Hello {name}h2>;
    
      return (
        <div>
          <Wrapper comp={heading} />
        div>
      );
    };
    
    export default App;
    

    请注意,React.ElementType可以为元素期望的属性类型传递一个泛型。

    在这个例子中,我们必须传递给它一个具有字符串类型的name属性的对象,因为那是heading组件接收的属性。

    // App.tsx
    import React from 'react';
    
    interface Props {
      // ✅ explicitly type props comp takes
      comp: React.ElementType<{name: string}>;
    }
    
    const Wrapper: React.FunctionComponent<Props> = props => {
      // 👇️ component names must start with capital letter
      const {comp: Comp} = props;
      return (
        <div>
          <Comp name="James" />
        div>
      );
    };
    
    const App: React.FunctionComponent = () => {
      const heading = ({name}: {name: string}) => <h2>Hello {name}h2>;
    
      return (
        <div>
          <Wrapper comp={heading} />
        div>
      );
    };
    
    export default App;
    

    现在我们显式地声明了元素在使用时所接受的comp属性的类型。这有助于我们在向组件传递属性时利用IDE的自动完成功能。

    我们也可以使用React.ComponentType,但这样我们就需要对属性声明类型。

    // App.tsx
    import React from 'react';
    
    interface Props {
      // 👇️ now using React.ComponentType 👇️
      comp: React.ComponentType<{name: string}>;
    }
    
    const Wrapper: React.FunctionComponent<Props> = props => {
      // 👇️ component names must start with capital letter
      const {comp: Comp} = props;
      return (
        <div>
          <Comp name="James" />
        div>
      );
    };
    
    const App: React.FunctionComponent = () => {
      const heading = ({name}: {name: string}) => <h2>Hello {name}h2>;
    
      return (
        <div>
          <Wrapper comp={heading} />
        div>
      );
    };
    
    export default App;
    

    React.ComponentType 中的泛型不能默认为any类型,因此我们需要显示地声明属性的类型。

    传递JSX元素

    如果你需要将JSX元素作为属性传递给组件,并且不是一个真正的组件,那么使用JSX.Element类型就是正确的。

    // App.tsx
    import React from 'react';
    
    interface Props {
      // 👇️ using JSX.Element type
      comp: JSX.Element;
    }
    
    const Wrapper: React.FunctionComponent<Props> = props => {
      const {comp: Comp} = props;
    
      // 👇️ use as {Comp}
      return <div>{Comp}div>;
    };
    
    const App: React.FunctionComponent = () => {
      const Heading = ({name}: {name: string}) => <h2>Hello {name}h2>;
    
      // 👇️ we are passing an actual JSX element
      // because we didn't pass it as comp={Heading}
      return (
        <div>
          <Wrapper comp={<Heading name="James" />} />
        div>
      );
    };
    
    export default App;
    

    我们将comp属性的类型声明为JSX.Element,因为我们传递了一个真正的JSX元素(不是组件)到Wrapper组件上。

    我们传递了一个JSX元素,是因为我们将comp={}作为属性进行传递,而不是comp={(props) =>

    Hello world

    }

    需要注意的是,在第一种情况下,我们传递的是一个JSX元素属性。而在第二种情况下,我们传递的是一个返回JSX元素的函数(一个功能组件)。

    在Wrapper组件中,我们不应尝试使用JSX元素作为组件。比如说,不要这么写,而要这么写{Comp}

    我们没有传递一个真正的组件作为属性,我们传递的是一个JSX元素,所以它不应该作为一个组件使用。

    更新类型包

    如果前面的建议都没有帮助,试着通过运行以下命令来更新你的React类型的版本。

    # 👇️ with NPM
    npm install react@latest react-dom@latest
    
    npm install --save-dev @types/react@latest @types/react-dom@latest
    
    # ----------------------------------------------
    
    # 👇️ with YARN
    yarn add react@latest react-dom@latest
    
    yarn add @types/react@latest @types/react-dom@latest --dev
    
  • 相关阅读:
    二叉树基础
    数字孪生技术在智慧城市应用的推进建议
    数据库分析工具explain
    阿里云OSS简单应用
    基于Python开发的五子棋小游戏(源码+可执行程序exe文件+程序配置说明书+程序使用说明书)
    使用任务定时执行软件的定时关机功能,控制电脑可用时间段
    Redis的介绍以及简单使用连接池
    速盾:cdn加速防ddos
    1.< tag-动态规划和路径组合问题>lt.62. 不同路径 + lt.63. 不同路径 II
    基于Java的私人牙医诊所(医院)系统
  • 原文地址:https://www.cnblogs.com/chuckQu/p/16589945.html