Do not use anonymous functions to construct React functional components

Steve Mao
2 min readMar 5, 2017

--

We strive to keep our code as concise as possible. If we need a stateless component, its recommended to use a simple functional component. AirBnB ESLint would error if you don’t do so. However, it’s tempted to write anonymous functional components especially when the component is very simple. Consider the following:

// in Foo.jsexport default (props) => (
<div>My component</div>
)

It works as expected and there’s probably no linting errors. However, there is no display name on the component by default. The drawbacks are:

1. If you use arrow functions, you are not following the class semantics.

EDIT: React components don’t have to be a class or constructor. But it’ll be more verbose if you use implicit name. Please skip this section.

Arrow function expression is probably one of the most overrated features in ES6. In fact, they cannot be used as constructors. Babel, however, transpiles them to normal function expressions which can be used as constructors. Although it works with implicit name, I believe React components should always follow the class or constructor semantics.

// in Foo.jsconst Foo = () => (
<div>My component</div>
)
export default Foo

2. It becomes harder to debug.

The display name on React components is a good way to find out the problem when there’s an exception the the console. It also makes it easier to see the component in the React tab.

3. It becomes harder to test.

Tools like Enzyme supports special selectors that can quickly find and test the child wrapper you want. If you don’t use display name, you might have problems. The error messages might be misleading. To those who are new to Enzyme like me, I didn’t even realise the selector was based on the display name, and thanks to jsx, I actually thought it was based on the “tag name”.

// in Bar.jsimport Foo from './Foo.js'
import { shallow } from 'enzyme'
function Bar(props) {
// `Foo` is not a "tag name"
return <Foo />
}
const wrapper = shallow(Bar)
wrapper.find('Foo') // It won't find the `Foo` component

In conclusion, you should always use the following pattern in simple React functional components:

export default function Foo(props) {
return (
<div>My component</div>
)
}

--

--