@bordoley says they all show up as StatelessComponent.
if you export default ({name}) => <div>{name}</div>
, it's not going to have a name, but that's on babel.
However, this works fine:
const MyStateless = ({name}) => <div>{name}</div>
.... somewhere
<MyStateless name="Sophia" />
Internally (Facebook) I was seeing.
<StatelessComponent>
<div>some text</div>
</StatelessComponent>
I'll generate a repro using public react to see if this is FB specific or not.
I am seeing this issue as well using public react.
My root component is a stateless component, if I run a production Browserify build (NODE_ENV:"production") with no mangling I get the following in React DevTools:
Here is my code for that same root component:
var MyRootComponent = () => (
<MyChildComponent />
);
What's your babel version? This is a babel issue I'm sure
On Mon, Nov 2, 2015 at 2:24 PM Steve Szczecina [email protected]
wrote:
I am seeing this issue as well using public react.
My root component is a stateless component, if I run a production
Browserify build (NODE_ENV:"production") with no mangling I get the
following in React DevTools:[image: statelesscomponent]
https://cloud.githubusercontent.com/assets/6877934/10894645/32f1fd9e-816d-11e5-8615-564e91edc3d0.pngHere is my code for that same root component:
var MyRootComponent = () => (
);—
Reply to this email directly or view it on GitHub
https://github.com/facebook/react-devtools/issues/267#issuecomment-153161776
.
I'm using Babelify 6.3.0 with Browserify
Maybe you don't have the function.name transform enabled? We probably rely on that.
Using browserify with coffee-reactify. Anything that I can do?
@joaomilho make an issue w/ coffee-reactify asking them about getting displayName
s enabled
For those using TypeScript you can do the following (example notice displayName
):
declare global {
interface Function {
displayName: string;
}
}
/********
*
* Primitives
*
********/
interface PrimitiveProps extends React.HTMLProps<HTMLDivElement>{};
/**
* Takes as much space as it needs, no more, no less
*/
export const Content = Radium((props: PrimitiveProps) => {
const style = csx.extend(props.style || {},csx.content);
return (
<div data-comment="Content" {...props} style={style}>
{props.children}
</div>
);
});
Content.displayName = "Content";
@basarat Old comment I know but hopefully this is useful for someone:
It's possible to get this working automatically using this Babel plugin which will use the filename to assign the function a name if it does not have one: https://github.com/wyze/babel-plugin-transform-react-stateless-component-name/
Few things to watch out for:
"react-hot-loader/babel"
plugin in your .babelrc
babel-loader
after ts-loader
for all your *.ts*
files) and you need to have module: "es6"
and jsx: "preserve"
in your tsconfig.json
or the plugin won't recognise that the components are actually stateless onesThis doesn't currently work (either in ES6 or Typescript) for SFCs wrapped in a higher order component, e.g. observe
from MobX. I'll raise an issue on the project for this.
Oh, or even easier, you can do away with the plugin and just name your component by putting into a constant, then exporting that separately, for example:
const MyComponent = () => <div>Hi</div>
export default MyComponent
Will show as MyComponent
in dev tools (with Typescript again, you need to set the module
option appropriately I think, although probably not jsx
).
Slightly more typing but probably clearer. Note this still doesn't seem to solve the HOC problem (already raised at: https://github.com/wyze/babel-plugin-transform-react-stateless-component-name/issues/2)
Ah (sorry to spam this thread!) – there is a way round the HOC problem, which is to do as the above and store the component in a named constant, then wrap it when exporting (rather than when creating), so instead of:
const MyComponent = observer(() => <div>Hi</div>)
export default MyComponent
You have:
const MyComponent = () => <div>Hi</div>
export default observer(MyComponent)
Which arguably reads better anyway :) (and allows you to export the non-decorated component if needed e.g. for testing)
@tomduncalf Just ran into this problem myself!
const { name } = element.type;
if (name && name.endsWith('Control')) {...}
Your fix worked until I turned mangling on with uglifyjs
Closing.
If you use Babel, es2015 preset contains function-name plugin that infers the name based on left hand side in expressions.
For Facebook internal use case, @spicyj recently fixed it by enabling the same transform.
I'm using TypeScript with:
export const MyComponent = ({text}) => (
<div>{text}</div>
);
And I just see <StatelessComponent>
in the dev tools... is there a fix for this?
is there a fix for this?
As mentioned before : https://github.com/facebook/react-devtools/issues/267#issuecomment-182658039 :rose:
declare global {
interface Function {
displayName?: string;
}
}
export const MyComponent = ({text}) => (
<div>{text}</div>
);
MyComponent.displayName = 'MyComponent';
Thanks that does work... I suppose I was asking if there's a way to make it work without explicitly writing the displayName
(which means you have to write the name twice).
I found that writing it this way seems to work:
function MyComponent({text}) {
return (
<div>{text}</div>
);
}
I found that writing it this way seems to work:
Yup, on modern browsers, cause they have .name
automatically. I'll use that myself as well from now on :rose: :heart:
On second thought both are equivalent on chrome as it also adds .name
for arrow assignments to variables e.g. run the following on the console
const x = ()=> undefined; function y(){}; console.log(x.name,y.name); // x y
export
might be throwing the emit (and/or) the v8's name detection off for const
:rose:
I think you're right about the export
confusing something. If I do this:
export const MyComponent = () => { };
I get <StatelessComponent>
in the dev tools.
But if I do this:
const MyComponent = () => { };
export {MyComponent};
I get <MyComponent>
in the dev tools as expected.
@aaronbeall Please file a bug with Babel if Babel doesn't add implicit name
to arrow functions when they're used as exports.
(Or with TypeScript if that's what you use)
@gaearon Yep I'm using TypeScript. It doesn't look like TS emits a .name
in any case... but I guess browsers are able to assign a name to functions when they are assigned to a var
but not when they are assigned to a prop of an exports
object? This example shows how TS emits to JS and every component name appears in dev-tools except export const Name = () =>
(the one I now use most, of course, lol).
Just stumbled on this thread. I've been running into an issue where the React Dev Tools tell me my component is called <Unknown>
whenever I do:
// MyComponent.js
export default (props) => <someJSX>;
// App.js
import MyComponent from './MyComponent.js';
But this works:
export default function MyComponent(props) {
return <someJSX>;
}
In case that's useful for anyone.
Yes, this is expected, because Babel only infers the arrow name if you assign it to something.
For example, this would also work:
const MyComponent = (props) => <someJSX />;
export default MyComponent;
I could fix the problem in typescript project by setting module
flag to es2015
and relying on webpacks native support for es modules. You have to set moduleResolution
to node
as well.
Most helpful comment
For those using TypeScript you can do the following (example notice
displayName
):Sample project work in progress :rose: