You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In [@types/react 16.9.48](https://github.com/DefinitelyTyped/DefinitelyTyped/pull/46643), the `React.VoidFunctionComponent` or `React.VFC` type was added for typing `children` explicitly.
340
340
However, please be aware that `React.VFC` and `React.VoidFunctionComponent` were deprecated in React 18 (https://github.com/DefinitelyTyped/DefinitelyTyped/pull/59882), so this interim solution is no longer necessary or recommended in React 18+.
341
341
342
-
Please use regular function components or `React.VFC` instead.
342
+
Please use regular function components or `React.FC` instead.
<summary><b>Small <code>React.ReactNode</code> edge case before React 18</b></summary>
1182
1182
1183
-
This code typechecks but has a runtime error:
1183
+
Before the [React 18 type updates](https://github.com/DefinitelyTyped/DefinitelyTyped/pull/56210), this code typechecked but had a runtime error:
1184
1184
1185
1185
```tsx
1186
1186
typeProps= {
@@ -1191,16 +1191,16 @@ function Comp({ children }: Props) {
1191
1191
return <div>{children}</div>;
1192
1192
}
1193
1193
function App() {
1194
-
return <Comp>{{}}</Comp>; // Runtime Error: Objects not valid as React Child!
1194
+
// Before React 18: Runtime error "Objects are not valid as a React child"
1195
+
// After React 18: Typecheck error "Type '{}' is not assignable to type 'ReactNode'"
1196
+
return <Comp>{{}}</Comp>;
1195
1197
}
1196
1198
```
1197
1199
1198
-
This is because `ReactNode` includes `ReactFragment` which allows a`{}`type, which is [too wide](https://github.com/DefinitelyTyped/DefinitelyTyped/issues/37596#issue-480260937). Fixing this would break a lot of libraries, so for now you just have to be mindful that `ReactNode` is not absolutely bulletproof.
1200
+
This is because `ReactNode` includes `ReactFragment` which allowed type`{}`before React 18.
1199
1201
1200
1202
[Thanks @pomle for raising this.](https://github.com/typescript-cheatsheets/react/issues/357)
1201
1203
1202
-
With the [React 18 type updates](https://github.com/DefinitelyTyped/DefinitelyTyped/pull/56210), `{}` is no longer allowed in `ReactFragment`.
Copy file name to clipboardExpand all lines: docs/advanced/patterns_by_usecase.md
+5-77
Original file line number
Diff line number
Diff line change
@@ -346,79 +346,6 @@ class List<T> extends React.PureComponent<Props<T>, State<T>> {
346
346
}
347
347
```
348
348
349
-
### Generic components with children
350
-
351
-
`children` is usually not defined as a part of the props type. Unless `children` are explicitly defined as a part of the `props` type, an attempt to use `props.children` in JSX or in the function body will fail:
352
-
353
-
```tsx
354
-
interfaceWrapperProps<T> {
355
-
item:T;
356
-
renderItem: (item:T) =>React.ReactNode;
357
-
}
358
-
359
-
/* Property 'children' does not exist on type 'WrapperProps<T>'. */
Type '{ children: string; item: string; renderItem: (item: string) => string; }' is not assignable to type 'IntrinsicAttributes & WrapperProps<string>'.
371
-
Property 'children' does not exist on type 'IntrinsicAttributes & WrapperProps<string>'.
372
-
*/
373
-
374
-
const wrapper = (
375
-
<Wrapperitem="test"renderItem={(item) =>item}>
376
-
{test}
377
-
</Wrapper>
378
-
);
379
-
```
380
-
381
-
[View in the TypeScript Playground](https://www.typescriptlang.org/play/?jsx=2#code/JYWwDg9gTgLgBAJQKYEMDG8BmUIjgcilQ3wFgAoC4AOxiSk3STgHUoUwx6AFHMAZwA8AFQB8cAN4U4cYHRAAuOMIDc0uEWoATegEl5SgBRyki5QEo4AXnHJ0MAHR2MAOQg615GWgAWwADZamkrOjqFuHhQAvhQUAPQAVHC8EFywAJ4EvgFBSNT4cFoQSPxw1BDwSAAewPzwENRwMOlcBGwcaSkCIqL4DnAJcRRoDXWs7Jz01nAicNV02qUSUaKGYHz8Su2TUF1CYpY2kupEMACuUI2G6jKCWsAAbqI3MpLrqfwOmjpQ+qZrGwcJhA5hiXleMgk7wEDmygU0YIhgji9ye6nMniinniCQowhazHwEjgcNy1CUdSgNAA5ipZAY4JSaXTvnoGcYGUzqNTDuIubS4FECrUyhU4Ch+PxgNTqCgAEb+ZgwCBNAkEXS0KnUKVoACCMBgVLlZzopQAZOMOjwNoJ+b0HOouvRmlk-PC8gUiiVRZUamMGqrWvgNYaaDr9aHjaa4Bbtp0bXa+hRBrFyCNtfBTfArHBDLyZqjRAAJJD+fwqrPIwvDUbwADuEzS02u4MEcamwKsACIs12NHkfn8QFYJMDrOJgSsXhIs4iZnF21BnuQMUA)
382
-
383
-
To work around that, either add `children` to the `WrapperProps` definition (possibly narrowing down its type, as needed):
384
-
385
-
```tsx
386
-
interfaceWrapperProps<T> {
387
-
item:T;
388
-
renderItem: (item:T) =>React.ReactNode;
389
-
children:string; // The component will only accept a single string child
or wrap the type of the props in `React.PropsWithChildren` (this is what `React.FC<>` does):
403
-
404
-
```tsx
405
-
interfaceWrapperProps<T> {
406
-
item:T;
407
-
renderItem: (item:T) =>React.ReactNode;
408
-
}
409
-
410
-
const Wrapper = <Textends {}>(
411
-
props:React.PropsWithChildren<WrapperProps<T>>
412
-
) => {
413
-
return (
414
-
<div>
415
-
{props.renderItem(props.item)}
416
-
{props.children}
417
-
</div>
418
-
);
419
-
};
420
-
```
421
-
422
349
## Typing Children
423
350
424
351
Some API designs require some restriction on `children` passed to a parent component. It is common to want to enforce these in types, but you should be aware of limitations to this ability.
@@ -593,11 +520,12 @@ If you want to conditionally render a component, sometimes is better to use [Rea
This was done [on purpose](https://github.com/DefinitelyTyped/DefinitelyTyped/pull/43265/). You can make it immutable if you have to - assign `React.Ref` if you want to ensure nobody reassigns it:
0 commit comments