facebook/react

displayName is set to "o" when minifiying Stateless function components via webpack

jimbolla opened this issue · 14 comments

Given a component defined as:

export const SubmitButton = ({readyState, defaultText, pendingText}) => (
    <button
        className="btn btn-lg btn-primary btn-block"
        type="submit"
        disabled={readyState === "pending"}>
        {
            readyState === "pending"
                ? (pendingText || defaultText)
                : defaultText
        }
    </button>
);

and minified with webpack's UglifyJsPlugin, you get components with displayName "o" in the React browser tools.

untitled

React component will use function name as the component's displayName if the displayName is not set.

var A = React.createClass({...})

The component's displayName is A, so since you minified the js code, I think React taken the correct function name o as the displayName.

It's problem with minification, not with react. Keep your variables names.

Uglify may be the culprit, but React is the one that suffers because of it. Not minifying code isn't really a good answer. I tried it with setting mangle: false and then it reported all the component names as StatelessComponent. My thought was maybe what we need is a Babel transform that adds whatever is needed.

@jimbolla Why you need uglify in development mode? I suggest you disable uglify in dev mode and enable it in production mode.

zpao commented

React doesn't do the transformation but feel free to file an issue against babel. If there's something React needs to do differently we can reopen.

You shouldn't minify in development mode anyway.

So our code shouldn't rely on displayName if it's going to get mangled? I use displayName to check if a child is a specific type, is this bad practice then?

@silvenon I wouldn't recommend it. Why not compare the type to the object exactly?

Mind blown 😮 Thanks a bunch!

For others who stumble onto this discussion:

import React from 'react';
import Foo from './Foo';

const Bar = (props) => {
  if (props.children.type === Foo) {
    // ...
  }

  return /* ... */;
};

If stateless functions support .propTypes and .defaultProps as static members, would it be possible to support .displayName in that same way as well?

@dminkovsky I haven't tried but I would expect that to already work?

@spicyj Totally works :D

wzup commented

React doesn't do the transformation but feel free to file an issue against babel.

@zpao Is that all you can say against this issue (as a person with a badge owner of the repo)? Then downvote.
Don't you have a solution, best React practice, for this issue yet? How is it possible?

@wzup

There’s no need to be combative about it. What @zpao is saying is that there is nothing on React side that needs to be fixed because React is not assigning names to your functions.

In production, it is expected that you will see minified names. That’s the whole point of minifying. It removes unnecessary code (and mangles identifiers).

In development, you should not be using minification in the first place. Minification is causing this, but you shouldn’t minify when you’re just developing. Minification is only needed when you ship a production version of your app to your users.

Finally, if you absolutely need those names in minified builds, you can assign them manually:

function Foo() {
  return <div />;
}
Foo.displayName = 'Foo';

Your bundle size will be larger in this case.

There is nothing to be done on the React side here, and it’s not a React issue (or, rather, not an issue at all). I’m locking the discussion because it is taking an unnecessarily emotional tone.

Feel free to file a new issue if you believe there is a bug with how React handles this, but please provide more context into why you think it’s a problem, and don’t be negative towards the people trying to help you.