Solution
JSX.Element;
: š© This doesn't account for arrays (e.g. multiple elements) at all.JSX.Element | JSX.Element[];
Ā š This doesn't accept strings.React.ReactChildren;
: š¤Ŗ Not at even an appropriate type; it's a utility function.React.ReactChild[];
: š Accepts multiple children, but it doesn't accept a single child.React.ReactNode;
: š Accepts everything.
This will get everything working as expected:
import React, { ReactNode } from "react";
type BoxProps = { children: ReactNode };
A helpful utility type
This is a pretty simple utility type that you could write yourself, but you don't have to.
type PropsWithChildren<P = unknown> = P & {
children?: ReactNode | undefined;
};
It's basically an easy way to say, "This component can render children." That's it. This means, we can refactor our example a little more.
import React, { PropsWithChildren } from "react";
const Box = ({ children }: PropsWithChildren) => {
return (
<section
className="m-4"
style={{ padding: "1em", border: "5px solid purple" }}
>
{children}
</section>
);
};
What if we wanted to add additional props? We can actually pass PropsWithChildren
an argument.
import React, { PropsWithChildren } from "react";
type BoxProps = { color?: "red" | "green" | "blue" };
const Box = ({ children, color = "red" }: PropsWithChildren<BoxProps>) => {
return (
<section
className="m-4"
style={{ padding: "1em", border: "5px solid purple", color }}
>
{children}
</section>
);
};
const Application = () => {
return (
<main className="m-8">
<Box color="green">
Just a string.
<p>Some HTML that is not nested.</p>
<Box>
<h2>Another React component with one child.</h2>
</Box>
<Box>
<h2 className="mb-4">A nested React component with two children.</h2>
<p>The second child.</p>
</Box>
</Box>
</main>
);
};
export default Application;
Alternatively, this will work, but the version that I showed you above is standard practice:
const Box = ({ children, color = "red" }: PropsWithChildren & BoxProps) => {
// ā¦
};
We'll learn how to make our own utility types like this in a bit.