简体   繁体   English

组件不能用作 JSX 组件。 它的返回类型 'Element[]' 不是有效的 JSX 元素

[英]Component cannot be used as a JSX component. Its return type 'Element[]' is not a valid JSX element

I'm currently getting the following error on the Todos component inside TodoApp.tsx : 'Todos' cannot be used as a JSX component.我目前在TodoApp.tsx中的Todos组件上收到以下错误:“Todos”不能用作 JSX 组件。 Its return type 'Element[]' is not a valid JSX element.它的返回类型“Element[]”不是有效的 JSX 元素。 Type 'Element[]' is missing the following properties from type 'Element': type, props, key类型“Element[]”缺少类型“Element”中的以下属性:type、props、key

And this is my folder structure这是我的文件夹结构

TodoApp.tsx

function TodoApp() {
  return (
    <Body>
      <AppDiv>
        <Form />
        <Todos />
        <Footer />
      </AppDiv>
    </Body>
  );
}

Todos.tsx

function Todos(): JSX.Element[] {
  const todos = useSelector((state: RootState) => state.todos);
  const footer = useSelector((state: RootState) => state.footer);

  if (footer.hideAll) {
    if (footer.showCompleted) {
      return todos
        .filter((todo) => !todo.completed)
        .map((todo: any) => (
          <>
            <ul>
              <Todo todo={todo} />
            </ul>
          </>
        ));
    }
    return todos.map((todo) => (
      <>
        <div>
          <Todo todo={todo} />
        </div>
      </>
    ));
  }

  return todos.map(() => (
    <>
      <div></div>
    </>
  ));
}

Todo.tsx

type Todo = {
  todo: TodoProps;
};

const Todo = ({ todo }: Todo) : JSX.Element => {
  const [isEditing, edit] = useState<boolean>(false);
  const dispatch = useDispatch();

  if (!isEditing) {
    return (
      <TodoDiv>
        <Li
          key={todo.id}
          completed={todo.completed}
          onClick={() => dispatch(completeTodo(todo.id))}
          // style={{
          //   textDecoration: todo.completed ? "line-through" : "none"
          // }}
        >
          {todo.text}
        </Li>
        <TodoBttns>
          <Button edit onClick={() => edit(!isEditing)}>
            <img src={editBttn} alt="Edit Button" />
          </Button>
          <Button delete onClick={() => dispatch(deleteTodo(todo.id))}>
            <img src={deleteBttn} alt="Delete Button" />
          </Button>
        </TodoBttns>
      </TodoDiv>
    );
  } else {
    return (
      <FormEdit>
        <InputForm key={todo.id} {...{ todo, edit }} />
      </FormEdit>
    );
  }
};

and the TodoProps interface is the following: TodoProps 接口如下:

interface TodoProps {
  text: string;
  completed: boolean;
  id: string;
}

already tried the fix of wraping the map items with fragments, but I still can't make it work.已经尝试用片段包装 map 项目的修复,但我仍然无法使其工作。 The only thing that as of now is fixing the issue is declaring at the top of Todos.tsx as this function Todos(): any到目前为止唯一能解决这个问题的是在Todos.tsx的顶部声明这个function Todos(): any

As a side note: I'm using Styled Components, but I don't think the issue is related to the library.附带说明:我正在使用样式化组件,但我认为该问题与库无关。

A component needs to return a single root element.组件需要返回单个根元素。 You can use fragments to package an array of elements as a single element, by using the fragment as that single root element.您可以使用片段将 package 元素数组作为单个元素,通过将片段用作单个根元素。

So this does nothing:所以这什么都不做:

function Todos(): JSX.Element {
  return todos.map(todo => (
    <>
      <li>{todo.task}</li>
    </>
  )
}

Because it's now returning an array of [<><li/></>, <><li/></>, ...] .因为它现在返回[<><li/></>, <><li/></>, ...]的数组。 That fragment needs to be the single root element.该片段需要是单个根元素。

You need to use the fragment like this:您需要像这样使用片段:

function Todos(): JSX.Element {
  return <>{
    todos.map(todo => <li>{todo.task}</li>)
  }</>
}

You nest all returned JSX in one single fragment.您将所有返回的 JSX 嵌套在一个片段中。

Using that pattern you may end up with somehting like this:使用这种模式,你最终可能会得到这样的结果:

function Todos(): JSX.Element {
  const todos = useSelector((state: RootState) => state.todos);
  const footer = useSelector((state: RootState) => state.footer);

  if (footer.hideAll) {
    if (footer.showCompleted) {
      return <>{
        todos
          .filter((todo) => !todo.completed)
          .map((todo: any) => (
            <ul>
              <Todo todo={todo} />
            </ul>
          ))
      }</>
    }
    return <>{
      todos.map((todo) => (
        <div>
          <Todo todo={todo} />
        </div>
      ))
    }</>
  }

  return <>{
    todos.map(() => (
      <div></div>
    ))
  }</>
}

// Works without error
<Todos />

Note how each return statement returns just one JSX.Element : the fragment.注意每个 return 语句如何只返回一个JSX.Element :片段。

Playground 操场

You need to return a JSX Element, not an array.您需要返回一个 JSX 元素,而不是一个数组。 Wrapping the whole component is a solution, but you need to do it outside of the map/filter function.包装整个组件是一种解决方案,但您需要在映射/过滤器 function 之外进行。

Todos.tsx

function Todos(): JSX.Element {
  const todos = useSelector((state: RootState) => state.todos);
  const footer = useSelector((state: RootState) => state.footer);

  if (footer.hideAll) {
    if (footer.showCompleted) {
      return (
        <>
          {todos.filter((todo) => !todo.completed).map((todo: any) => (
            <ul>
              <Todo todo={todo} />
            </ul>
           ));
          }
        </>
    }
    return (
      <>
        {todos.map((todo) => (
          <div>
            <Todo todo={todo} />
          </div>
        ));
        }
      </>
  }

  return (
    <>{todos.map(() => <div />)}</>
  );
}

In case anyone is facing issue with React + Typescript stack, try adding below setting in tsconfig.json.如果有人遇到 React + Typescript 堆栈的问题,请尝试在 tsconfig.json 中添加以下设置。 It worked for me.它对我有用。

"allowSyntheticDefaultImports": true “allowSyntheticDefaultImports”:真

In my case, it was a forgotten import.就我而言,这是一个被遗忘的导入。 Basically copy-pasted some of my code and forgot to import one of the components and this was the error message I get.基本上复制粘贴了我的一些代码并忘记导入其中一个组件,这是我得到的错误消息。

There's a possibility that you have installed (and probably failed) a new package, which could also cause this error.您可能已经安装(并且可能失败)新的 package,这也可能导致此错误。

If that's the case (that you have recently installed and failed or cancelled a package), you can delete node_modules and run npm i or yarn install then try again.如果是这种情况(您最近安装并失败或取消了一个包),您可以删除node_modules并运行npm iyarn install然后重试。

You need to install types for react npm install @types/react or yarn add @types/react您需要为 react 安装类型npm install @types/reactyarn add @types/react

Sometimes this error can occur when you use the switch case syntax to render your component.当您使用switch case语法呈现组件时,有时会发生此错误。

For example:例如:

switch (loading) {
    case "pending":
      return <span>Pending</span>;
    case "succeeded":
      return <span>Succeeded</span>;
    case "failed":
      return <span>Failed</span>;

Sometimes your loading status can mistakenly have a value that you didn't specify in the case , so your component will return undefined .有时您的加载状态可能会错误地具有您未在case中指定的值,因此您的组件将返回undefined Therefore, you should add a default value:因此,您应该添加一个default值:

default: return <span>¯\_(ツ)_/¯</span>;

For a scenario when someone has upgraded to later React , eg, 16 -> 17 it could start happening.对于有人升级到更高版本的React的场景,例如, 16 -> 17 ,它可能会开始发生。

Now, while looking for @types/react in your project, you could notice many npm packages have @types/react: "*", .现在,在您的项目中查找@types/react时,您会注意到许多npm包具有@types/react: "*", The solution to get rid off the problem, in that scenario, would be to add into your package.json :在这种情况下,摆脱问题的解决方案是添加到您的package.json

"resolutions": {
  "@types/react": "^17.0.38"
}

I'm facing the same issue about this error.关于这个错误,我面临同样的问题。 I add the below code to my package.json file.我将以下代码添加到我的package.json文件中。

"resolutions": {
  "@types/react": "17.0.2",
  "@types/react-dom": "17.0.2",
  "graphql": "^16.5.0"
},

Then, Run yarn install on a terminal.然后,在终端上运行yarn install

It works for me.这个对我有用。

This answer is related to same problem on react-native. Adding typescript to my newly created react-native app and moving App.js to App.tsx, I met the same error for component named Section.这个答案与 react-native 上的相同问题有关。将 typescript 添加到我新创建的 react-native 应用程序并将 App.js 移动到 App.tsx,我遇到了名为 Section 的组件的相同错误。 The solution for me was a component type React.Fc<{...}> .我的解决方案是组件类型React.Fc<{...}> This is the problematic Section component after the fix when all errors disappeared and my app started as expected.当所有错误都消失并且我的应用程序按预期启动时,这是修复后有问题的部分组件。

 import React, { ReactNode } from 'react';
 import {
   SafeAreaView,
   ScrollView,
   StatusBar,
   StyleSheet,
   Text,
   useColorScheme,
   View,
 } from 'react-native';
 
 import {
   Colors,
   DebugInstructions,
   Header,
   LearnMoreLinks,
   ReloadInstructions,
 } from 'react-native/Libraries/NewAppScreen';
 
 const Section: React.FC<{  
  children: ReactNode;   
  title: string; 
}> = ({children, title}) => {
   const isDarkMode = useColorScheme() === 'dark';
   return (
     <View style={styles.sectionContainer}>
       <Text
         style={[
           styles.sectionTitle,
           {
             color: isDarkMode ? Colors.white : Colors.black,
           },
         ]}>
         {title}
       </Text>
       <Text
         style={[
           styles.sectionDescription,
           {
             color: isDarkMode ? Colors.light : Colors.dark,
           },
         ]}>
         {children}
       </Text>
     </View>
   );
 };

Another common cause of the "Component cannot be used as a JSX component" error is when we return anything other than a JSX element or null from a component, or forget to return a value. “组件不能用作 JSX 组件”错误的另一个常见原因是当我们从组件返回 JSX 元素或 null 以外的任何内容时,或者忘记返回值。

The App component returns undefined because we have placed our return statement on one line and the JSX code on the next without using parentheses . App 组件返回 undefined ,因为我们将 return 语句放在一行,将 JSX 代码放在下一行,而没有使用括号

We aren't allowed to return undefined from a component, so the error occurs.我们不允许从组件返回undefined ,所以错误发生了。

Add the following code添加以下代码

"paths": {
   "react": [ "./node_modules/@types/react" ]
 }

to tsconfig.json file, in compilerOptionstsconfig.json文件,在 compilerOptions

Here is how my code looks like now:这是我的代码现在的样子:

{
  "compilerOptions": {
    "jsx":"react",
    "strict": true,
    "paths": {
      "react": [ "./node_modules/@types/react" ]
    }
  }
}

It is telling the typescript compiler that when it encounters a reference to the "react" module, it should look for the actual implementation in the "./node_modules/@types/react" directory.它告诉 typescript 编译器,当遇到对“react”模块的引用时,它应该在“./node_modules/@types/react”目录中查找实际实现。

In my case I forgot to put back ticks after styled(PreviousStyledElement);就我而言,我忘记在styled(PreviousStyledElement);之后放回刻度线。 After I put them the code started to work.在我把它们放好之后,代码就开始工作了。

 export const MyNewStyledElement = styled(PreviousStyledElement)``;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 组件不能用作 JSX 组件。 它的返回类型'元素 | undefined' 不是有效的 JSX 元素 - Component cannot be used as a JSX component. Its return type 'Element | undefined' is not a valid JSX element “X”不能用作 JSX 组件。 它的返回类型 'Element[]' 不是有效的 JSX 元素 - 'X' cannot be used as a JSX component. Its return type 'Element[]' is not a valid JSX element 不能用作 JSX 组件。 它的返回类型“void”不是有效的 JSX element.ts(2786) - cannot be used as a JSX component. Its return type 'void' is not a valid JSX element.ts(2786) &#39;Router&#39; 不能用作 JSX 组件。 它的实例类型“BrowserRouter”不是有效的 JSX 元素 - 'Router' cannot be used as a JSX component. Its instance type 'BrowserRouter' is not a valid JSX element “组件”不能用作 JSX 组件。 它的元素类型&#39;ReactElement<any, any> | Component&lt;{}, any, any&gt;&#39; 不是有效的 JSX 元素 - 'Component' cannot be used as a JSX component. Its element type 'ReactElement<any, any> | Component<{}, any, any>' is not a valid JSX element 'Provider' 不能用作 JSX 组件。 它的实例类型'Provider<anyaction> ' 不是有效的 JSX 元素。 TS2786</anyaction> - 'Provider' cannot be used as a JSX component. Its instance type 'Provider<AnyAction>' is not a valid JSX element. TS2786 RC-dock 库的 &#39;DockLayout&#39; 不能用作 JSX 组件。 它的实例类型“DockLayout”不是有效的 JSX 元素 - RC-dock library's 'DockLayout' cannot be used as a JSX component. Its instance type 'DockLayout' is not a valid JSX element “组件”不能用作 JSX 组件。 下一步 - 'Component' cannot be used as a JSX component. Nextjs 'Home' 不能用作 JSX 组件。 使用反应 typescript - 'Home' cannot be used as a JSX component. using react typescript TypeScript 错误:(具有 MUI 样式的组件)不能用作 JSX 元素 - TypeScript error: (component with MUI style) cannot be used as a JSX element
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM