Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type error: JSX element type '{} | null | undefined' is not a constructor function for JSX elements

Tags:

I have a React component called HandleQuery that handles the results of an Apollo GraphQL query:

import React, { ReactNode } from 'react';  import { CenteredMessage } from './centered-message';  export interface HandleQueryProps {     loading: boolean,     error?: Error,     children: ReactNode }  export const HandleQuery = ({ loading, error, children }: HandleQueryProps) => {     if (loading) {         return <CenteredMessage>Loading...</CenteredMessage>;     }      if (error) {         return <CenteredMessage>{error.message}</CenteredMessage>;     }      return children; }; 

When this component is used in another component it does not compile:

import React from 'react';  import { useQuery } from 'react-apollo-hooks'; import gql from 'graphql-tag'; import { HandleQuery } from '..'; import { MutationType } from '../../graphql-types'; import { AuthorsPanel } from './authors-panel'; import { GET_AUTHORS } from './authors-queries'; import { AuthorMutated } from './__generated__/AuthorMutated';  export class AuthorsContainer extends React.Component {     render() {         const { loading, error, data } = useQuery(GET_AUTHORS);         return (             <!-- THIS LINE PRODUCES A COMPILER ERROR -->             <HandleQuery loading={loading} error={error}>                 <AuthorsPanel data={data} />             </HandleQuery>         );     } } 

The use of HandleQuery above produces the following error:

Type error: JSX element type '{} | null | undefined' is not a constructor function for JSX elements. Type 'undefined' is not assignable to type 'Element | null'. TS2605

What does this mean and how can I get rid of it?

Update

Converting AuthorsContainer to a function component does not eliminate the error:

export const AuthorsContainer = () => {     const { loading, error, data } = useQuery(GET_AUTHORS);     return (         <HandleQuery loading={loading} error={error}>             <AuthorsPanel data={data} />         </HandleQuery>     ); }; 

Update 2 Implemented suggestion from @FredyC:

import React from 'react';  import { CenteredMessage } from './centered-message';  export interface HandleQueryProps {     loading: boolean;     error?: Error; }  export const HandleQuery: React.FC<HandleQueryProps> = ({     loading,     error,     children }) => {     if (loading) {         return <CenteredMessage>Loading...</CenteredMessage>;     }      if (error) {         return <CenteredMessage>{error.message}</CenteredMessage>;     }      return children; }; 

Now the error on the container component has gone away, but a new compiler error has popped up on the HandleQuery component:

Type error: Type '({ loading, error, children }: PropsWithChildren<HandleQueryProps>) => {} | null | undefined' is not assignable to type 'FunctionComponent<HandleQueryProps>'.   Type '{} | null | undefined' is not assignable to type 'ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<any, any, any>)> | null'.     Type 'undefined' is not assignable to type 'ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<any, any, any>)> | null'.  TS2322 
like image 308
Naresh Avatar asked Feb 27 '19 12:02

Naresh


People also ask

What is JSX element []?

What is JSX? JSX stands for JavaScript XML. JSX allows us to write HTML in React. JSX makes it easier to write and add HTML in React.

What is JSX element in typescript?

JSX is an embeddable XML-like syntax. It is meant to be transformed into valid JavaScript, though the semantics of that transformation are implementation-specific.

Can not be used as a JSX component?

The error "Component cannot be used as a JSX component" occurs for multiple reasons: Returning an array of JSX elements instead of a single element. Returning any value other than a JSX element or null from a component. Having outdated version of React typings.

Does not have any construct or call signatures?

The error "JSX element type does not have any construct or call signatures" occurs when we try to pass an element or a react component as props to another component but type the prop incorrectly. To solve the error, use the React. ElementType type.


1 Answers

There is a long term issue regarding ReactNode. I don't understand specifics, but it's something hard-wired in TypeScript itself and is being worked on.

Either way, a solution should be easy. Don't use ReactNode with functional components :) The children prop is implicitly included in React.FC type.

The same problem goes with returning children. It can be either overcome by wrapping into <React.Fragment> or <div> if you prefer, but since it's just a type error, you can convince TypeScript that you know what you are doing :)

import React, { ReactNode } from 'react';  import { CenteredMessage } from './centered-message';  export interface HandleQueryProps {     loading: boolean,     error?: Error, }  export const HandleQuery: React.FC<HandleQueryProps> = ({ loading, error, children }) => {     if (loading) {         return <CenteredMessage>Loading...</CenteredMessage>;     }      if (error) {         return <CenteredMessage>{error.message}</CenteredMessage>;     }      return children as ReactElement<any>; }; 
like image 67
FredyC Avatar answered Sep 27 '22 19:09

FredyC