I've created a component roughly like this, serving to wrap the behavior of the SVG text
element to add more sophisticated handling of the string. You can imagine something similar for generating simple a
tags or spans
or defn
or whatnot…
export let MultilineText = ({children:text, ...props}) =>
<text {...props}>
{text.split(' ').map((str,i) =>
<tspan key={i} dy="1em">{str}</tspan>
)}
</text>
The key point is that I've taken the children
prop and assigned it to text
locally, which makes the assumption that it will be a string that I can split!
However the React.Children docs discuss "dealing with the this.props.children opaque data structure" (emphasis mine). So technically my code's assumption could break in the future?
I would propose a React.Children.text
helper that would guarantee stable behavior to this code:
export let MultilineText = ({children, ...props}) =>
<text {...props}>
{React.Children.text(children).split(' ').map((str,i) =>
<tspan key={i} dy="1em">{str}</tspan>
)}
</text>
Specifically:
This would behave very much like the React.children.onlyChild logic and its invariant check, but expecting typeof children === 'string'
rather than a ReactElement.isValidElement(children)
. (See also https://github.com/facebook/react/issues/1104.)
owever the React.Children docs discuss "dealing with the this.props.children opaque data structure" (emphasis mine). So technically my code's assumption could break in the future?
cc @bvaughn @gaearon do you guys think there is any chance of this in the future?
Why not get text
through a property instead of children? It seems like the only reason you're getting text through children would be because you like how it looks, but that's never a good idea... or perhaps I'm missing something?
On another note, you could easily write your own implementation React.Children.text
using the standard helpers, if you want to do it that way and stay future compatible for sure.
I think we need to clarify how opaque children
really need to be. If there's a chance that React will ever use a different data structure to represent string children (instead of just the string itself) then it makes sense to add a helper. But I don't think that's likely, maybe @gaearon can chime in.
I don't think it's likely.
I needed something like this for a Button
component that I was writing. It accepts icons as children, but I didn't want to make consumers explicitly provide a label
prop. Here's the solution I used:
/**
* The `BaseButton` component accepts any number of children. This flexibility
* is used to support easily adding icons as children. However, we only want
* to include strings when building accessible labels. Otherwise, it would say
* [object Object] in the label.
*/
const getLabelFromChildren = (children) => {
let label = '';
React.Children.map(children, (child) => {
if (typeof child === 'string') {
label += child;
}
});
return label;
};
In case anyone else ends up here, I discovered this package today and so far it works great!
https://github.com/fernandopasik/react-children-utilities
import Children from 'react-children-utilities'
const MyComponent = ({ children }) => Children.onlyText(children)
onlyText
is recursive, and children
can be any React Node. Awesome!
Most helpful comment
I needed something like this for a
Button
component that I was writing. It accepts icons as children, but I didn't want to make consumers explicitly provide alabel
prop. Here's the solution I used: