React报错之JSX element type does not have any construct

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

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

// App.tsx import React from 'react'; interface Props { comp: JSX.Element; }const Wrapper: React.FunctionComponent = props => { const {comp: Comp} = props; // ?? JSX element type 'Comp' does not have any construct or call signatures.ts(2604) return (); }; const App: React.FunctionComponent = () => { const heading = ({name}: {name: string}) => Hello {name}; return (); }; 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 => { // ? component names must start with capital letter const {comp: Comp} = props; return (); }; const App: React.FunctionComponent = () => { // ? takes a name prop const heading = ({name}: {name: string}) => Hello {name}; return (); }; 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 => { // ? component names must start with capital letter const {comp: Comp} = props; return (); }; const App: React.FunctionComponent = () => { const heading = ({name}: {name: string}) => Hello {name}; return (); }; 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 => { // ? component names must start with capital letter const {comp: Comp} = props; return (); }; const App: React.FunctionComponent = () => { const heading = ({name}: {name: string}) => Hello {name}; return (); }; 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 => { const {comp: Comp} = props; // ? use as {Comp} return {Comp}; }; const App: React.FunctionComponent = () => { const Heading = ({name}: {name: string}) => Hello {name}; // ? we are passing an actual JSX element // because we didn't pass it as comp={Heading} return (); }; export default App;

我们将comp属性的类型声明为JSX.Element,因为我们传递了一个真正的JSX元素(不是组件)到Wrapper组件上。
我们传递了一个JSX元素,是因为我们将comp={}作为属性进行传递,而不是comp={(props) => Hello world}
需要注意的是,在第一种情况下,我们传递的是一个JSX元素属性。而在第二种情况下,我们传递的是一个返回JSX元素的函数(一个功能组件)。
在Wrapper组件中,我们不应尝试使用JSX元素作为组件。比如说,不要这么写,而要这么写{Comp}
我们没有传递一个真正的组件作为属性,我们传递的是一个JSX元素,所以它不应该作为一个组件使用。
更新类型包 【React报错之JSX element type does not have any construct】如果前面的建议都没有帮助,试着通过运行以下命令来更新你的React类型的版本。
# ? with NPM npm install react@latest react-dom@latestnpm install --save-dev @types/react@latest @types/react-dom@latest# ----------------------------------------------# ? with YARN yarn add react@latest react-dom@latestyarn add @types/react@latest @types/react-dom@latest --dev

    推荐阅读