35

I have the following piece of code (codesandbox):

import { ComponentType, ReactNode } from "react";

type DatetimeCell = ({ value }: { value: string }) => ReactNode;

function getDateTimeCell(): DatetimeCell {
  return ({ value }) => value;
}

function buildCell({
  value
}: {
  value: string;
}): ComponentType<{ value: string }> {
  const DateTimeCell = getDateTimeCell();
  return ({ value }) => <DateTimeCell value={value} />;
}

When returning in buildCell I get the error:

'DateTimeCell' cannot be used as a JSX component.
  Its return type 'ReactNode' is not a valid JSX element.

I thought ReactNode would be the most general type for valid JSX, but it seems like that is not the case.
Why is ReactNode not valid JSX and how can I solve this issue?

Edit: I know that wrapping value in React fragments solves the issue. However, in this specific application I need the type DatetimeCell to be able to return any valid JSX. So string should be included.

2
  • Try ReactElement instead of ReactNode Commented May 26, 2022 at 13:01
  • That indeed solves the type error. However, it creates a new one. Now I cannot return a string in DatetimeCell. Commented May 26, 2022 at 13:03

4 Answers 4

13

Why is ReactNode not valid JSX ?? => https://stackoverflow.com/a/72353143/10146901

and how can I solve this issue? => Just Return JSX.Element as function return type.

function buildCell({ value }: { value: string }): JSX.Element { // ... my codes }

Solution of your codesandbox

Sign up to request clarification or add additional context in comments.

5 Comments

I opened your solution and there still is an error in buildCells return.
I think this is what you meant right? codesandbox.io/s/react-typescript-forked-sugr36 However, it still throws an error.
@mgottsch 'buildCell' is defined but never used . This is just a basic warning not an error. Use the buildCell function somewhere, this warning will be gone
No, this is not what I mean. There is an error in the return function. 'DateTimeCell' cannot be used as a JSX component. Its return type 'ReactNode' is not a valid JSX element. Type 'undefined' is not assignable to type 'Element | null'.ts(2786)
This just gives a different error,Its type 'Element' is not a valid JSX element type
4

I faced the same issue, and resolved it by updating the TypeScript version to 5.4.2. This resolved the issue.

Comments

1

Part of ReactNode type is undefined, which is not a valid JSX element I think.

The easiest way to solve the problem would be just to type DatetimeCell as Component as well, and always return an element from getDateTimeCell - just wrap the result in a fragment.

import React, { ComponentType } from 'react';

type DatetimeCell = ComponentType<{ value: string }>;

function getDateTimeCell(): DatetimeCell {
  return ({ value }) => <>{value}</>;
}

function buildCell({ value }: { value: string }): ComponentType<{ value: string }> {
  const DateTimeCell = getDateTimeCell();
  return ({ value }) => <DateTimeCell value={value} />;
}

3 Comments

I don't understand why undefined is not valid JSX. React does not crash when you use undefined as JSX, so why are the typings like this? (see here for proof: codesandbox.io/s/infallible-payne-yx4xes?file=/src/App.js). In my application, I need DatetimeCell to be able to return string, so I cannot use your solution (See edit).
I suspect undefined is not allowed just to stop people from forgetting to return something.
This is bad, because it prevents me from returning props.children since it can be undefined...
-3

When you invoke DateTimeCell it expects a JSX element (ReactNode) to be returned. You are currently returning a string and not a React node in your getTimeCell function. I recommend typing your functional components using the FC type provided by react as below:

import { FC } from "react";

type Props = { value: string };
type DatetimeCell = FC<Props>;

function getDateTimeCell(): DatetimeCell {
  return ({ value }) => <>{value}</>;
}

function buildCell({ value }: Props): DatetimeCell {
  const DateTimeCell = getDateTimeCell();
  return ({ value }) => <DateTimeCell value={value} />;
}

buildCell({ value: "hello" });

1 Comment

string is a ReactNode type ReactNode = ReactElement | string | number | ReactFragment | ReactPortal | boolean | null | undefined; (from @types/react)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.