How to fix Strings are not allowed as React children. Did you mean to use an array? in React
This TypeScript error occurs when a component's children prop is typed too strictly, preventing strings from being passed as children. It typically happens when using JSX.Element instead of React.ReactNode.
Quick fix
Fixes Strings are not allowed as React children. Did you mean to use an array?
// ❌ Too strict - rejects strings
interface ButtonProps {
children: JSX.Element;
}
// ✅ Correct - accepts strings and elements
interface ButtonProps {
children: React.ReactNode;
}
export function Button({ children }: ButtonProps) {
return <button>{children}</button>;
}
// Now this works:
<Button>Click me</Button>- Change children type to React.ReactNode
- Use PropsWithChildren for cleaner syntax
- Use specific types only when truly needed
- Wrap strings in fragments if type cannot be changed
// ❌ Too strict - rejects stringsinterface ButtonProps {children: JSX.Element;}// ✅ Correct - accepts strings and elementsinterface ButtonProps {children: React.ReactNode;}export function Button({ children }: ButtonProps) {return <button>{children}</button>;}// Now this works:<Button>Click me</Button>Strings are not allowed as React children. Did you mean to use an array?
What this error means
This error appears in TypeScript projects when you've restricted the type of the children prop in a way that excludes strings. React normally accepts strings as valid children, but if you type children as JSX.Element or JSX.Element[], TypeScript will reject string children at compile time. The error message suggests using an array because TypeScript thinks you're trying to pass multiple children but only provided a single string. However, the real issue is that the children type doesn't include string as a valid type. This is a TypeScript type checking error, not a runtime React error. React itself has no problem rendering strings as children - this is entirely about how you've defined your component's TypeScript types.
Typical symptoms
- TypeScript compilation error when passing string children to a component
- Error message specifically mentions "Strings are not allowed as React children"
- Component works in JavaScript but fails in TypeScript
- Error occurs when passing text directly between component tags
- Suggestions to use an array instead of a string
Common causes
- Component children prop typed as JSX.Element instead of React.ReactNode
- Component children prop typed as JSX.Element[] which excludes strings
- Using ReactElement type which only accepts React elements
- Custom children type that excludes string primitives
- Overly strict type definitions in component props interface
How to fix "Strings are not allowed as React children. Did you mean to use an array?"
The most common fix is to use React.ReactNode for the children prop, which accepts strings, numbers, elements, and more:
// ❌ Too strict - rejects strings
interface ButtonProps {
children: JSX.Element;
}
// ✅ Correct - accepts strings and elements
interface ButtonProps {
children: React.ReactNode;
}
export function Button({ children }: ButtonProps) {
return <button>{children}</button>;
}
// Now this works:
<Button>Click me</Button>React.ReactNode is the standard type for children and includes:
- string
- number
- React.ReactElement
- React.ReactFragment
- null
- undefined
- boolean
React provides a utility type PropsWithChildren that automatically adds a ReactNode children prop:
import { PropsWithChildren } from 'react';
// Without other props
type ButtonProps = PropsWithChildren;
// With additional props
interface ButtonBaseProps {
variant: 'primary' | 'secondary';
onClick?: () => void;
}
type ButtonProps = PropsWithChildren<ButtonBaseProps>;
export function Button({ children, variant, onClick }: ButtonProps) {
return (
<button className={variant} onClick={onClick}>
{children}
</button>
);
}This approach is cleaner and ensures consistency across your codebase.
Only restrict children types if you genuinely need to enforce a specific structure:
// If you ONLY accept specific components:
interface TabsProps {
children: React.ReactElement<TabProps> | React.ReactElement<TabProps>[];
}
// But note: this prevents string children
<Tabs>
<Tab label="First">Content</Tab> {/* ✅ Works */}
Some text {/* ❌ Error */}
</Tabs>
// If you need validation beyond types, use runtime checks:
export function Tabs({ children }: PropsWithChildren) {
React.Children.forEach(children, (child) => {
if (!React.isValidElement(child) || child.type !== Tab) {
throw new Error('Tabs only accepts Tab components as children');
}
});
return <div className="tabs">{children}</div>;
}Runtime validation is more flexible than TypeScript types for complex children requirements.
If you're working with a third-party library where you cannot change the type definitions:
// Library component only accepts JSX.Element
import { StrictComponent } from 'some-library';
// ❌ Doesn't work
<StrictComponent>
Hello World
</StrictComponent>
// ✅ Wrap in fragment
<StrictComponent>
<>Hello World</>
</StrictComponent>
// ✅ Or use a span/div
<StrictComponent>
<span>Hello World</span>
</StrictComponent>This wraps your string in a JSX element, satisfying the type requirement.
Advanced notes
Why React.ReactNode is the standard:
React.ReactNode is defined as:
type ReactNode =
| ReactElement
| string
| number
| ReactFragment
| ReactPortal
| boolean
| null
| undefined;This covers everything React can render, making it the most flexible and appropriate type for children in most cases.
JSX.Element vs React.ReactElement:
JSX.Element is actually an alias for React.ReactElement with any types:
declare global {
namespace JSX {
interface Element extends React.ReactElement<any, any> {}
}
}Both exclude string, number, null, and undefined, which are valid React children.
Type safety vs flexibility trade-off:
While TypeScript can't prevent you from passing wrong component types at compile time (everything is seen as JSX.Element), runtime validation with React.Children or React.isValidElement is more effective for enforcing component structure requirements.
Children as a render prop:
For strict type control, consider using a render prop pattern instead of children:
interface ListProps<T> {
items: T[];
renderItem: (item: T) => React.ReactNode;
}
function List<T>({ items, renderItem }: ListProps<T>) {
return <ul>{items.map((item, i) => <li key={i}>{renderItem(item)}</li>)}</ul>;
}This provides better type inference and control than trying to type-check children.
Frequently asked questions
- What does "Strings are not allowed as React children. Did you mean to use an arra" mean?
- This error appears in TypeScript projects when you've restricted the type of the children prop in a way that excludes strings. Element[], TypeScript will reject string children at compile time. The error message suggests using an array because TypeScript thinks you're trying to pass multiple children but only provided a single string.
- How do I fix "Strings are not allowed as React children. Did you mean to use an arra"?
- This TypeScript error occurs when a component's children prop is typed too strictly, preventing strings from being passed as children. It typically happens when using JSX.Element instead of React.ReactNode.
- What causes "Strings are not allowed as React children. Did you mean to use an arra"?
- Component children prop typed as JSX.Element instead of React.ReactNode Component children prop typed as JSX.Element[] which excludes strings Using ReactElement type which only accepts React elements
- Is the "Strings are not allowed as React children. Did you mean to use an arra" error serious?
- It is a low-severity error — more of a blocker than a risk. The steps above resolve it.