Home > database >  Component with function child yields error "Its return type 'ReactNode' is not a vali
Component with function child yields error "Its return type 'ReactNode' is not a vali

Time:01-23

Consider the following react code: (codesandbox)

import type { ReactNode } from 'react';

type RenderCallbackProps = {
  children: (o: { a: number }) => ReactNode,
};

function RenderCallback({ children }: RenderCallbackProps) {
  return (children({ a: 123 }));
}

export default function App() {
  return (
    <RenderCallback>
      {({ a }) => (
        <h1>{a}</h1>
      )}
    </RenderCallback>
  );
}

This causes the error message:

function RenderCallback({ children }: RenderCallbackProps): ReactNode
'RenderCallback' 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)

Why?

Where is the undefined coming from?

How to fix that?

CodePudding user response:

Where is the undefined coming from?

That's part of what ReactNode means. ReactNode is: ReactChild | ReactFragment | ReactPortal | boolean | null | undefined, or basically all of the stuff that you could legally put as the child of a <div>. But while you can put a undefined as a child of a div, it can't be the only thing returned by a component, so you get an error when you try to do return (children({ a: 123 }));

You can fix this one of two ways. If you want to continue to allow null/undefined/boolean etc to be passed in, then just make sure that RenderCallback always wraps it in an element. A fragment will be enough:

function RenderCallback({ children }: RenderCallbackProps) {
  return (
    <>
      {children({ a: 123 })}
    </>
  )
}

Or if you don't want to allow those values, then you can change the types on the callback. For example only allowing elements:

children: (o: { a: number }) => ReactElement,
  • Related