React: Wrong "Each child should have a key prop" warning with babel-plugin-transform-react-inline-elements

Created on 2 Aug 2017  Â·  17Comments  Â·  Source: facebook/react

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

Feature / Bug

What is the current behavior?

Warning: Each child in an array or iterator should have a unique "key" prop. See https://fb.me/react-warning-keys for more information.
    in div
    in div
    in LandingPage (created by RouterContext)
    in Transition (created by CSSTransition)
    in CSSTransition
    in div (created by TransitionGroup)
    in TransitionGroup
    in AnimateComponentSwap
    in section
    in div
    in div
    in App (created by inject-App-with-UIStore)
    in inject-App-with-UIStore (created by RouterContext)
    in RouterContext (created by Router)
    in Router
    in MuiThemeProvider
    in Provider

The warning seems to say there is a div inside of a div inside of my LandingPage component which has incorrect key props.

But in actual fact it was this element inside a div inside the component that was causing the problem:

<h1 ref="landingLabel" className="label">
    I'm looking for things to do in
</h1>

When I add a key prop, such as key="landing-label" the warning disappears.

But, the warning also disappears when I remove the ref="landingLabel" ref string. I know that this is now deprecated, but I don't get any further warnings about it - and it seems like string refs and key prop warnings might be combining somehow.

Another reason why it was confusing is because my component does not have any array inside of it for its children, or iterate over anything - which I think is where keys are actually only really required. The component looks like this:

<div className="full-page-content">
   <div className="landing-blurb">
      <div key="logo" className="logo">
        <LogoSvg />
      </div>
      <div className="animation">
         <TransitionGroup>
            {svgAnimation}
         </TransitionGroup>
      </div>
      <h1 ref="landingLabel" className="label">
          I'm looking for things to do in
      </h1>
   </div>
</div>

What is the expected behavior?

A more targeted warning - either a problem with key props or a problem with string refs... (or both, but clearly separated) And also targeted to the correct element - in this case an h1 instead of a div.

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

React 16.0.0-beta.2

Most helpful comment

Are these still applicable in React Fiber?

This part hasn’t changed but I encourage you to measure performance of your application rather than rely on intuition about these plugins. I don’t have any guarantees they help in your case.

It seems that the babel plugin transform-react-inline-elements is causing this warning to pop up because when I rebuild without it in .babelrc the warning is not showing any more.

This might (or might not) a bug with it.

In either case, these plugins should not be used in development. They are meant to only be used in production (in which mode React doesn’t emit warnings).

From inline-elements page:

This transform should be enabled only in production (e.g., just before minifying your code) because although it improves runtime performance, it makes warning messages more cryptic and skips important checks that happen in development mode, including propTypes.

From constant-elements page:

This transform should be enabled only in production (e.g., just before minifying your code) because although it improves runtime performance, it makes warning messages more cryptic.

So seems like this is expected and not our bug.

All 17 comments

Can you provide an isolated example reproducing this? It’s a bit hard to guess what went wrong without running the code.

Sure, just put this together quick: https://github.com/lostpebble/react-key-prop-warn

In doing that I've actually whittled down the cause of the problem. It seems that the babel plugin transform-react-inline-elements is causing this warning to pop up because when I rebuild without it in .babelrc the warning is not showing any more.

I am making use of the plugins transform-react-constant-elements and transform-react-inline-elements because of the supposed performance benefits. Are these still applicable in React Fiber?

Are these still applicable in React Fiber?

This part hasn’t changed but I encourage you to measure performance of your application rather than rely on intuition about these plugins. I don’t have any guarantees they help in your case.

It seems that the babel plugin transform-react-inline-elements is causing this warning to pop up because when I rebuild without it in .babelrc the warning is not showing any more.

This might (or might not) a bug with it.

In either case, these plugins should not be used in development. They are meant to only be used in production (in which mode React doesn’t emit warnings).

From inline-elements page:

This transform should be enabled only in production (e.g., just before minifying your code) because although it improves runtime performance, it makes warning messages more cryptic and skips important checks that happen in development mode, including propTypes.

From constant-elements page:

This transform should be enabled only in production (e.g., just before minifying your code) because although it improves runtime performance, it makes warning messages more cryptic.

So seems like this is expected and not our bug.

Thanks so much for your feedback, and all your work on this project! Much appreciated 🙂

Thanks for reporting issues. One thing I’m curious about: can you reproduce the same issue in 15? Or do you believe 16 made it more cryptic in this case?

Just downgraded that test project to 15.6.1 and it's not reporting any errors at all while using transform-react-inline-elements.

In my main project where I first noticed this warning, I can't remember seeing it and I'm always trying to squash any warnings that come along. Pretty sure my project was running without any warnings on v15 before the upgrade, same as the test project.

So in this case, I would say v16 has somehow clashed with the way transform-react-inline-elements does things.

Interesting. Let's keep it open as low priority for investigation if we find the time. Or you can investigate it too :-)

Cool, will keep an eye out on it during the next few releases :)

Though it does seem pretty low priority as I shouldn't have been using the babel plugins in the first place during dev. Probably should also be looked at by whoever is working on the babel plugin, as there might be some changes in v16 which aren't playing nice and causing the warnings to crop up... kind of makes me wonder if it's production-fit for v16 at the moment.

There shouldn't be any related API changes in React so it should be compatible.

I ran into the same issue. Upgraded to React 16 and started getting unique "key" prop warnings where I wasn't using any arrays or iterators. It's definitely related to the transform-react-inline-elements plugin and refs, since if I remove either one of those, the warning disappears.

I see that the plugin injects a _jsx helper into the source, but where refs are used, it falls back to React.createElement. It did this with v15 too, but perhaps now the mixing of those is causing issues?

Edit: It's not just string refs by the way; the issue occurs with callback refs too.

To be clear, it is expected that you’ll get meaningless warnings if you attempt to use inline-elements or constant-elements plugins in development.

This is because these plugins must _not_ be used in development.
Using them in development is not supported.

That’s documented on both of these plugins’ pages.

Yep, that's definitely clear. I only prefer to use the same plugins in development as long as they work (I've found issues in production faster that way).

To be fair, I also interpreted the disclaimer as "makes [existing] warning messages more cryptic," not "causes new and incorrect warning messages to appear," but I guess I'm wrong about that. :) I only became worried because the API didn't change, and v15 didn't output these warnings, so there might be some new underlying incompatibility.

Yea, I’m still curious why this happens. I’d love if somebody could look into it. If it’s an easy fix then it would be nice to make it before shipping 16.

But I wouldn’t want to make an impression that it’s supported.

Well, I can see why it happens now, but don't know if there's a good way to fix it. It happens when React.createElement is passed in as a child of _jsx, e.g.:

_jsx('div',
  {style: {position: 'relative', display: 'inline-block'}},
  void 0,
  React.createElement('div', {ref: 'help', className: 'img icon help'}),
);

The div.help is never passed to validateChildKeys (because _jsx doesn't call that, obviously), so its _store.validated flag remains false, triggering the warning in validateExplicitKey later (somewhere through reconcileChildrenArray).

Not sure what changed between v15 and v16 there, but not surprising something broke since it's bypassing internal flags.

If Babel was able to use _jsx for the div.help I guess it'd be fixed, but the plugin page mentions that it won't, so it's intentional for some reason:

The plugin will still use React.createElement when `ref` or `object rest spread` is used

I couldn't find in the git history and/or don't know enough about React internals to know why this is needed.

Maybe it wasn't firing earlier for the same reason https://github.com/facebook/react/issues/9727 and https://github.com/facebook/react/issues/9174 weren't firing (but should have).

I'm going to close this since it's not supported to use inline-elements transform in development. If somebody finds a simple fix though, happy to take a PR.

I am receiving these errors from a production build. Is this expected? If so, can I configure react such that it doesn't emit these warnings?

If you see warnings, you are not using a production build.

How to verify that you use the production build: https://reactjs.org/docs/optimizing-performance.html#use-the-production-build

Was this page helpful?
0 / 5 - 0 ratings