facebook / react

The library for web and native user interfaces.
https://react.dev
MIT License
229.85k stars 47.06k forks source link

[React 19] Using spread with binary conditional in JSX causes error in dev env for case of using legacy JSX transform #29902

Open undeletable opened 5 months ago

undeletable commented 5 months ago

Summary

Prerequisites

Result

Error is thrown when conditional is evaluated to false:

Uncaught TypeError: Cannot use 'in' operator to search for '__self' in false
    at exports.createElement (chunk-Y64RAOT6.js?v=f4a3421f:775:86)
    at App (App.jsx:3:13)
    at callComponentInDEV (react-dom_client.js?v=f4a3421f:785:18)
    at renderWithHooks (react-dom_client.js?v=f4a3421f:3510:24)
    at updateFunctionComponent (react-dom_client.js?v=f4a3421f:4521:21)
    at beginWork (react-dom_client.js?v=f4a3421f:5096:20)
    at runWithFiberInDEV (react-dom_client.js?v=f4a3421f:864:18)
    at performUnitOfWork (react-dom_client.js?v=f4a3421f:7688:83)
    at workLoopSync (react-dom_client.js?v=f4a3421f:7580:43)
    at renderRootSync (react-dom_client.js?v=f4a3421f:7561:13)

Code fragment where it's thrown:

        if (null != config) for (propName in didWarnAboutOldJSXRuntime || !("__self" in config) || "key" in config || (didWarnAboutOldJSXRuntime = true, warn("Your app (or one of its dependencies) is using an outdated JSX transform. Update to the modern JSX transform for faster performance: https://react.dev/link/new-jsx-transform")), hasValidRef(config), hasValidKey(config) && (checkKeyStringCoercion(config.key), typeString = "" + config.key), config) hasOwnProperty.call(config, propName) && "key" !== propName && "__self" !== propName && "__source" !== propName && (i[propName] = config[propName]);

Reproduction

https://github.com/undeletable/jsx-spread-with-react-19-rc Click 'Toggle count button state' to reproduce

saul-atomrigs commented 5 months ago

I think the "modern" way to do is to conditionally assign the event handler directly within the onClick, like for example:

<button
  onClick={isCountButtonActive ? () => setCount(currentCount => currentCount + 1) : undefined}
>
  Increment count
</button>
undeletable commented 5 months ago

@saul-atomrigs Thanks. I know several ways to work that around, including your approach. But the code in my example should work too, as it's valid and spread operator usage too, and not less 'modern' one for sure. That's why I've raised the issue.

undeletable commented 5 months ago

I'm going to work on the fix

github-actions[bot] commented 2 months ago

This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!

undeletable commented 2 months ago

Still an issue. Upgraded to the latest RC in repository with reproduce.

undeletable commented 2 months ago

There's PR with fix: https://github.com/facebook/react/pull/29925 Updated it with the latest changes from main branch