React: Rendering a `String` class instance in an expression renders each letter as a text node

Created on 27 Nov 2019  路  8Comments  路  Source: facebook/react

Do you want to request a feature or report a bug?

Report a bug

What is the current behavior?

If you attempt to render a String in an expression, it will render each letter as a child node.

From an accessibility standpoint, this does matter. A screen reader like Apple's VoiceOver utility will attempt to read every text node, meaning that it will attempt to read each letter. This would mean an impacted experience for blind users.

From a display perspective, this doesn't matter, because browsers will group the nodes next to each other, inline.

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem. Your bug will get fixed much faster if we can run your code and it doesn't have dependencies other than React. Paste the link to your JSFiddle (https://jsfiddle.net/Luktwrdm/) or CodeSandbox (https://codesandbox.io/s/new) example below:

https://codesandbox.io/s/string-constructor-issue-f5t5x

  • Open the sandbox in a new window.
  • Examine the DOM. See that text nodes are created for each letter from the rendered String instance.
  • Open Apple's VoiceOver and read the page. Hear that all letters in the rendered String instance are spelled out, instead of the words being spoken.

What is the expected behavior?

I would expect a String instance to be rendered the same as a string literal type.

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?

Happening on React DOM 16.8.6, Chrome 80.0, Mac OSX

Stale

Most helpful comment

All 8 comments

The issue of rendering this.

<p>{new String("Text inside of a string constructor")}</p>

Can be fixed using toString

<p>{new String("Text inside of a string constructor").toString()}</p>

With given example, the Codesandbox shows a linter warning.
Do not use String as a constructor.

It is considered bad practice to use String as a constructor.

There's almost never any reason to create the object version of any of them explicitly, and doing so can indeed lead to confusion

https://stackoverflow.com/a/41458207/815507

Is there a good reason to use string constructor for text rendering?
If there is, maybe we could use the toString method to solve this issue?

The application I work on uses extensions of the String type in order to allow for better compile-time auditing and analysis of our application code in TypeScript. toString() is not an option because type information would be erased.

The linter opinion aside, the behavior of React in this case is unexpected and surprising. We had no reason to expect for it to render out child nodes for each letter.

We had no reason to expect for it to render out child nodes for each letter.

That sounds fair. Vanilla JS example doesn't indicate that either.
https://codesandbox.io/s/testing-string-constructor-rendering-9k3mr

toString() is not an option because type information would be erased.

Is type information important for rendering?
I could be wrong, but do we care whether we use string object or string literal when we render it?

<p>{myStringObject.toString()}</p>

Speculation:
new String("Text inside of a string constructor")
is of type Object and is iterable. I am guessing React detects that and render it by iterating it.

Thank you for the fast PR! In our case we want to retain type information in JSX purposes for static analysis. As you've noted, vanilla JS does not indicate it, and additionally Angular and Vue show the expected behavior. Will keep an eye on that merge request :)

In our case we want to retain type information in JSX purposes for static analysis.

I don't believe that calling .toString() (or '' + new String('...')) would prevent your ability to do static analysis to detect rendered strings. Why would it?

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contribution.

Closing this issue after a prolonged period of inactivity. If this issue is still present in the latest release, please create a new issue with up-to-date information. Thank you!

Was this page helpful?
0 / 5 - 0 ratings