Issue
<MyComponent>
<button>Click me</button>
</MyComponent>
interface MyComponentProps {
children: ???;
}
const MyComponent: FC<MyComponentProps> = ({children}) => {
const string = children.??? //I want the string to be "Click me"
}
I tried so many combinations but I always get undefined, thank you so much for your help.
Solution
As others have pointed out, you probably shouldn't be accessing the props of a child, as it is an anti-pattern in React. However, it is possible.
Let's do it right, and write a function to do so safely.
First a few type predicate helpers.
const isElement = (child: React.ReactNode): child is React.ReactElement =>
(child as React.ReactElement)?.props !== undefined;
const isLeaf = (child: React.ReactNode): child is React.ReactText =>
typeof child === 'string' || typeof child === 'number';
Then a recursive function, that recursively maps over children, picking out string and numbers. Because children can be an array, we return an array of strings or numbers.
function extractText(children: React.ReactNode): React.ReactText[] {
return React.Children.toArray(children).reduce<React.ReactText[]>((previous, child) => {
if (isElement(child)) {
return [...previous, ...extractText(child.props.children)];
}
if (isLeaf(child)) {
return [...previous, child];
}
return previous;
}, []);
}
Finally, put it all together.
const MyComponent = ({ children }: { children: React.ReactNode }): JSX.Element => {
const string = extractText(children)[0];
console.log(string); // Click me
return <>{children}</>;
};
export default function App() {
return (
<MyComponent>
<button>Click me</button>
</MyComponent>
);
}
Link to Sandbox
Answered By - Benjamin
Answer Checked By - - Willingham (ReactFix Volunteer)