Skip to content

Add a React.Children.text helper #9255

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
natevw opened this issue Mar 24, 2017 · 9 comments
Closed

Add a React.Children.text helper #9255

natevw opened this issue Mar 24, 2017 · 9 comments

Comments

@natevw
Copy link

natevw commented Mar 24, 2017

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:

  • if "children" represents a single text node, return its string value
  • otherwise throw an assertion error

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 #1104.)

@aweary
Copy link
Contributor

aweary commented Apr 5, 2017

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?

@syranide
Copy link
Contributor

syranide commented Apr 6, 2017

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.

@aweary
Copy link
Contributor

aweary commented Apr 10, 2017

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.

@gaearon
Copy link
Collaborator

gaearon commented Oct 4, 2017

I don't think it's likely.

@gaearon gaearon closed this as completed Oct 4, 2017
@leerob
Copy link

leerob commented Jan 8, 2019

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;
};

@TSMMark
Copy link

TSMMark commented Jun 12, 2019

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!

@machineghost
Copy link

Does the React project have a published criteria for what makes it into the library proper, and what should be handled by 3rd party libraries?

This seems like something that'd be better in React, so if there was such criteria I'd love to grok it.

@Kikobeats
Copy link

my two cents:

import React, { isValidElement } from 'react'

const hasChildren = element =>
  isValidElement(element) && Boolean(element.props.children)

const ReactChildrenText = children => {
  if (hasChildren(children)) return ReactChildrenText(children.props.children)
  return children
}

@landsman
Copy link

landsman commented Nov 8, 2022

Right now I handling task where I receiving converted markdown to React elements and I want to get text for headline anchors. Such overkill without this suggested helper field/method.

EDIT: this package solved my issue: https://github.com/lhansford/react-to-text

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants