Reputation: 52193
Using TypeScript with React we no longer have to extend React.Props
in order for the compiler to know that all react component props can have children:
interface MyProps { }
class MyComponent extends React.Component<MyProps, {}> {
public render(): JSX.Element {
return <div>{this.props.children}</div>;
}
}
However, it doesn't seem to be the case for stateless functional components:
const MyStatelessComponent = (props: MyProps) => {
return (
<div>{props.children}</div>
);
};
Emits the compile error:
Error:(102, 17) TS2339: Property 'children' does not exist on type 'MyProps'.
I guess this is because there's really no way for the compiler to know that a vanilla function is going to be given children
in the props argument.
So the question is how should we use children in a stateless functional component in TypeScript?
I could go back to the old way of MyProps extends React.Props
, but the Props
interface is marked as deprecated, and stateless components don't have or support a Props.ref
as I understand it.
So I could define the children
prop manually:
interface MyProps {
children?: React.ReactNode;
}
First: is ReactNode
the correct type?
Second: I have to write children as optional (?
) or else consumers will think that children
is supposed to be an attribute of the component (<MyStatelessComponent children={} />
), and raise an error if not provided with a value.
It seems like I'm missing something. Can anyone provide some clarity on whether my last example is the way to use stateless functional components with children in React?
Upvotes: 156
Views: 164945
Reputation: 67
Personally it's pretty easy in later versions of react when using typescript such as Next-JS 14
export default function TwButton({children, type, role } : {children?:
ReactNode,
type?:"submit" | "reset" | "button",
role?: "OK" | "CANCEL" | "RESET"
}){
....
}
Upvotes: 0
Reputation: 105
You can just add children to the component and if it is connected to a container that is all you need.
const MyComponent = ({
children
}) => {
return <div>{children}</div>
}
Upvotes: 3
Reputation: 977
Simpler answer: Use ReactNode
:
interface MyProps {
children?: React.ReactNode
}
If children
is optional or not (i.e. having ?
or not) depends on your component. The ?
is the most concise way to express that, so nothing wrong with that.
On history: This was not necessarily the correct answer back when originally asked: The type ReactNode
was added in (almost) its current form in March 2017 by this pull request only, but almost everyone reading this today should be on a modern enough version of React.
Lastly, about passing children
as "attribute" (which, in React lingo, would be passing it as "prop", not attribute): It is possible, but in most cases reads better when passing JSX children:
<MyComponent>
<p>This is part of the children.</p>
</MyComponent>
reads more easily than
<MyComponent children={<p>This is part of the children.</p>} />
Upvotes: 18
Reputation: 2419
You can use
interface YourProps { }
const yourComponent: React.SFC<YourProps> = props => {}
Upvotes: -2
Reputation: 3413
React 16.8 Update:
Since React 16.8, the names React.SFC
and React.StatelessComponent
are deprecated. Actually, they have become aliases for React.FunctionComponent
type or React.FC
for short.
You would use them the same way though:
const MyStatelessComponent : React.FunctionComponent<MyProps> = props =>
<div>
<p>{props.propInMyProps}</p>
<p>{props.children}</p>
</div>
Before React 16.8 (Older):
For now, you can use the React.StatelessComponent<>
type, as:
const MyStatelessComponent : React.StatelessComponent<{}> = props =>
<div>{props.children}</div>
What I have added there is setting the return type of the component to React.StatelessComponent
type.
For a component with your own custom props (like MyProps
interface):
const MyStatelessComponent : React.StatelessComponent<MyProps> = props =>
<div>
<p>{props.propInMyProps}</p>
<p>{props.children}</p>
</div>
Now, props
has got the children
property as well as those from MyProps
interface.
I checked this in typescript version 2.0.7
Additionally, you can use React.SFC
instead of React.StatelessComponent
for brevity.
Upvotes: 134
Reputation: 3260
You can use React.PropsWithChildren<P>
type for your props:
interface MyProps { }
function MyComponent(props: React.PropsWithChildren<MyProps>) {
return <div>{props.children}</div>;
}
Upvotes: 187