Should we declare React functional components with a const or a function?
If you have been writing React functional components for a while now, you may have encountered two ways of declaring a component - an arrow function or a function declaration.
There are two ways of declaring a component.
- Using an arrow function
- Using function declaration
If you look at the React documentation, you can see that the components declarations are done with the function syntax:
React documentation: Components and Props
Using an arrow function:
const App = () => {
return(
..
);
}
And using function declaration :
function App() {
return(
..
);
}
If your component only returns JSX, then the first option (arrow function) seems to be shorter.
const App = () => <>Hello!</>;
Versus:
function App() {
return <>Hello!</>;
}
Exporting the default component
But if when are exporting your component as default, this is no longer the case:
const App = () => {};
export default MyComponent;
Versus:
export default function App() {
return <>Hello!</>;
}
You could also omit the name and directly export the function expression:
export default function() {
return <>Hello!</>;
}
Hoisting
This is where function syntax shines! Let's look at an example starting with the arrow function syntax:
const FirstComponent = () => {}
const SecondComponent = () => {}
const App = () => (
<>
<FirstComponent />
<SecondComponent />
</>
);
export default App;
This syntax is valid. But things get hairy if you declare your other components after your main component.
const App = () => (
<>
<FirstComponent />
<SecondComponent />
</>
);
const FirstComponent = () => <>First</>
const SecondComponent = () => <>Second</>
export default App;
Your linter will throw an error because the components are used before they have been declared.
But if we declared your components using function syntax:
function App() {
return (
<>
<FirstComponent />
<SecondComponent />
</>
);
}
const FirstComponent = () => { return <>First</> }
const SecondComponent = () => { return <>Second</> }
export default App;
Generics
If you are using TypeScript and using generic types in your component, you have to use the function syntax.
interface Item {
name: string;
}
interface ListProps<T> {
items: T[];
onClick: (item: T) => void;
}
function List<T = unknown>(props: ListProps<T>) {
return <>TODO</>
}
function App() {
const items: Item[] = [{ name: 'Sean'}];
const onClick = (item: Item) => console.log(item);
return <List<Item> items={items} onClick={onClick} />
}
At the end of the day, you don't have to pick one or the other. But having these differences in mind will help you to decide which option to use when you write your component declarations.
Summary
- Function declarations are actually fewer characters than const arrow function statements:
// 16 characters
function App() {
}
// 20 characters
const App = () => {
}
- If you are writing multiple components in one file, it's better to use function syntax as hoisting may come into effect
- If you want to use generics, you will have to use function syntax