Skip to content
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

Bug: unintended .valueOf() maybe? #20594

Closed
dimaqq opened this issue Jan 15, 2021 · 1 comment · Fixed by #20617
Closed

Bug: unintended .valueOf() maybe? #20594

dimaqq opened this issue Jan 15, 2021 · 1 comment · Fixed by #20617
Labels
Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug

Comments

@dimaqq
Copy link
Contributor

dimaqq commented Jan 15, 2021

While chasing tc39/proposal-temporal#1224 where I mistakenly pasted a ZonedDateTime into JSX, I discovered that:

  • react-reconciler doesn't like arbitrary objects (fair)
  • calls throwOnInvalidObjectType on such objects, source code of which looks completely fine†
  • but said source code gets compiled into ... "foo" + newChild + "bar" ...
  • at the same time, react explicitly chose not to valueOf() objects in Consider using .valueOf() before providing fragment warning. #4769
  • this specific type throws unconditionally on .valueOf (I'm ambivalent about that decision)

function throwOnInvalidObjectType(returnFiber: Fiber, newChild: Object) {
if (returnFiber.type !== 'textarea') {
invariant(
false,
'Objects are not valid as a React child (found: %s). ' +
'If you meant to render a collection of children, use an array ' +
'instead.',
Object.prototype.toString.call(newChild) === '[object Object]'
? 'object with keys {' + Object.keys(newChild).join(', ') + '}'
: newChild,
);
}
}

‡ compiled to throw Error( "Objects are not valid as a React child (found: " + (Object.prototype.toString.call(newChild) === '[object Object]' ? 'object with keys {' + Object.keys(newChild).join(', ') + '}' : newChild) + "). If you meant to render a collection of children, use an array instead." );

So, react won't use valueOf to render an element, but will use it to report and error about an element.
Maybe the "compilation" or interpolation of invariant is wrong?
Or perhaps %s handling in invariant is wrong?
Maybe my assumptions are wrong?
Maybe that type is wrong?

React version: 17.0.1

Steps To Reproduce

  1. return <div>{ new Temporal.Instant(0n).toZonedDateTimeISO("Europe/Berlin") }</div>;

Link to code example: https://github.com/dimaqq/test-temporal

@dimaqq dimaqq added the Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug label Jan 15, 2021
@rickhanlonii
Copy link
Member

Confirmed.

@dimaqq do you want to put in a PR to fix it? You should be able to just change newChild to Object.prototype.toString.call(newChild) in the three or so places that this error is thrown.

That change would result in this message:

Objects are not valid as a React child (found: [object Temporal.ZonedDateTime]). If you meant to render a collection of children, use an array instead."

rickhanlonii pushed a commit that referenced this issue Jan 20, 2021
koto pushed a commit to koto/react that referenced this issue Jun 15, 2021
justingrant added a commit to justingrant/react that referenced this issue Aug 16, 2021
Using the `+` operator to concatenate strings and objects is problematic
because `+` calls `valueOf` which will throw for some types.
See facebook#20594 for details.

This commit globally replaces `'' + obj` with `''.concat(obj)`, which
does the same thing but doesn't call `valueOf` before converting to a
string.

It also updates the code example in the lint rule that encouaged use of
this problematic pattern.
justingrant added a commit to justingrant/react that referenced this issue Aug 16, 2021
Using the `+` operator to concatenate strings and objects is problematic
because `+` calls `valueOf` on the object. `valueOf` will throw for
some types of objects. See facebook#20594 for details.

This commit globally replaces `'' + obj` with `''.concat(obj)`, which
does the same thing but doesn't call `valueOf` before converting to a
string.

It also updates the code example in the lint rule that encouaged use of
this problematic pattern.
justingrant added a commit to justingrant/react that referenced this issue Aug 16, 2021
Using the `+` operator to concatenate strings and objects is problematic
because `+` calls `valueOf` on the object. `valueOf` will throw for
some types of objects. See facebook#20594 for details.

This commit globally replaces `'' + obj` with `''.concat(obj)`, which
does the same thing but doesn't call `valueOf` before converting to a
string.

It also updates the code example in the lint rule that encouaged use of
this problematic pattern.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants