'Get text content from React element stored in a variable
Is there a way to get text content from a React element stored in a variable without ref?
There is a functional component, that receives title
prop, which contains react element:
function component({ title }) {
const content = title.textContent() // Need Something like this
}
and this title
prop might have react node like: <div>Some Title</div>
. But I'd like to get only content of the node, in a variable before rendering it. Is it possible?
When I console.log title
variable this is the output, The content I want is inside props.children
array, so is there a method to get it without traversing through keys:
Solution 1:[1]
I've not found a better solution than indeed traversing the object to get the text. In TypeScript:
/**
* Traverse any props.children to get their combined text content.
*
* This does not add whitespace for readability: `<p>Hello <em>world</em>!</p>`
* yields `Hello world!` as expected, but `<p>Hello</p><p>world</p>` returns
* `Helloworld`, just like https://mdn.io/Node/textContent does.
*
* NOTE: This may be very dependent on the internals of React.
*/
function textContent(elem: React.ReactElement | string): string {
if (!elem) {
return '';
}
if (typeof elem === 'string') {
return elem;
}
// Debugging for basic content shows that props.children, if any, is either a
// ReactElement, or a string, or an Array with any combination. Like for
// `<p>Hello <em>world</em>!</p>`:
//
// $$typeof: Symbol(react.element)
// type: "p"
// props:
// children:
// - "Hello "
// - $$typeof: Symbol(react.element)
// type: "em"
// props:
// children: "world"
// - "!"
const children = elem.props && elem.props.children;
if (children instanceof Array) {
return children.map(textContent).join('');
}
return textContent(children);
}
I don't like it at all, and hope there's a better solution.
Solution 2:[2]
use https://github.com/fernandopasik/react-children-utilities
import Children from 'react-children-utilities'
const MyComponent = ({ children }) => Children.onlyText(children)
Solution 3:[3]
Thanks @Arjan for the effort and solution, but I have changed something in the component, to get the title in string format.
Now I have added another props to the component: renderTitle
which is a function to render custom react title.
So now I am passing title as string:
<Component
title="Some content"
renderTitle={(title) => <div>{title}</div> }
/>
and inside component:
<div>{renderTitle ? renderTitle(title) : title}</div>
With this implementation, I can use title as string to do what I want inside the component, while also supporting custom title render.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Moe Singh |
Solution 3 |