JSX 元素类型没有任何构造或调用签名
JSX element type does not have any construct or call signatures
当我们尝试将元素或 React 组件作为 props 传递给另一个组件但输入错误的 prop 时,会出现错误“JSX 元素类型没有任何构造或调用签名”。
要解决错误,请使用React.ElementType
类型。
下面是错误如何发生的示例。
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 组件作为 prop 传递给该Wrapper
组件,但已将其键入为JSX.Element
.
输入道具为React.ElementType
要解决该错误,请将 prop 键入 as React.ElementType
。
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
类型属性的对象string
,因为这是组件采用的属性heading
。
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 a 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
来解决错误
我们也可以使用React.ComponentType
,但是我们需要输入道具。
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 a 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;
泛型 inReact.ComponentType
不默认为any
类型,因此我们需要显式键入 props。
将 JSX 元素作为 props 传递给组件
如果您需要将 JSX 元素作为 props 传递给组件,而不是实际组件,那么JSX.Element
是正确的类型。
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
prop as 是JSX.Element
因为我们将实际的 JSX 元素(不是组件)传递给Wrapper
组件。
我们正在传递一个 JSX 元素,因为我们传递的是 ascomp={<Heading />}
而不是comp={(props) => <h2>Hello world</h2>}
。
我们不应该尝试在我们的组件中使用 JSX 元素作为组件Wrapper
,例如不要做<Comp />
,而是做{Comp}
。
我们没有传递一个实际的组件作为 prop,我们传递了一个 JSX 元素,所以它不应该被用作一个组件。
如果将多个子元素传递给采用单个 的组件
JSX.Element
,则会出现错误
This JSX tag’s children prop expects single child of type Element, but multiple children were provided。
更新你的 React.js 类型
如果之前的建议都没有帮助,请尝试通过运行以下命令来更新 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
我已经写了一篇关于
如何正确更新 React.js 类型的详细指南。
额外资源
您可以通过查看以下教程来了解有关相关主题的更多信息: