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,