For some time now I have been wondering if there is a benefit to using function
over const
when declaring functional components, and vice versa. So, I decided to do a little research, and I will sum it up for you in this article.
TLDR
It does not really matter whether you use one or the other. The most important technical difference is that functional components defined using function
are hoisted whereas those using const
are not. However, this has no pragmatic consequence as long as you define your components in separate files and import them at the top of the files where you need them. This is most likely the way that you are structuring your files anyway, which is why it does not really make a difference
The biggest benefit that I found to using the function
syntax is when using Visual Studio Code as editor. This is because VSC gives you the option to refactor a function
to a new file, but this option is not available if you have used the const
syntax.
Additionally, some people have a preference towards one of them because of readability. However, that is subjective and you can decide for yourself what you prefer.
In the end it is the difference in utility from VSC that makes me prefer function
over const
when declaring functional components in React. Apart from that, I have not found any practical differences between the two.
For the curious, you can find further details below.
A technical difference — Hoisting
JavaScript has a concept called Hoisting which allows for variables and functions to be declared on lines below the lines where they are used. It is a bit complex, and it would require more explanation to fully understand than I want to include here. So, instead I will show you what it means in terms of our components.
The following code gist contains two modified index.tsx
files, which are normally the entry point to your React application. The first one is invalid and will cause an error, whereas the second one is valid. The only difference between them is where the Header
component is initialized. In the first file it is initialized on line 14 which is below line 9 where it is being used. And in the second file it is initialized on line 7 which is before its use on line 13.
This screenshot of a code sandbox shows the error that will occur, when the const
function is used before it is initialized. (Don’t mind the red squiggly line on line 2)
Code sandbox showing an invalid use of the const keyword
Let’s now take a look at the same code, just using the function
keyword for the Header
component instead.
Code sandbox showing a valid use of the keyword function
The code sandbox above shows that the code runs correctly when using the function
syntax. (The squiggly red line on line 11 occurs because the current linting rules do not approve of using a function before it is defined, however this is only linting.)
This shows that there could be a potential technical benefit to using function
instead of const
.
But does it really matter in a real world project…
Photo by Juan Rumimpunu on Unsplash
I would argue no.
This is because I will almost always define my components in separate files, and then import them into the files where I want to render them. And my import statements are always at the top of my files. Because of this, my const
components will always be defined above the lines of code that actually run them.
This means that even in the cases like the following it does not become a problem.
Code sandbox showing that defining components with const, is not really a problem even though they are not hoisted
But wait a moment, how does the above example work? Why is there no problem in using InnerComponent
inside of App
? Even though it is defined below App
.
My theory is, that the determining factor is the order of the code at runtime and not at compile/interpretation time. The entry point for rendering the app at runtime is the call to root.render(<App />);
on line 8, which happens after the import statement on line 3 in index.tsx
. As such, the initialization of InnerComponent
is above root.render(<App />);
and is therefore already initialized once the App
component needs it.
Let’s take a look at a small toy example in pure JavaScript to make it easier to wrap your head around.
Working example with call to later defined function after its definition
In the screenshot of the code sandbox above the InnerComponent
is defined below the definition of the function expression AppEntry
. However, the call to AppEntry
happens after InnerComponent
has been initialized, and as a result there is no problem at runtime, even though it is a function created using const
. (This resembles most of our use cases in React)
Example showing how InnerComponent cannot be used before its initialization at runtime
If instead we move the AppEntry
call up before InnerComponent
, then we see the problem occurring because the const
function expression is not being hoisted. (But I don’t think this will ever happen to you, since the entry point of your app is most likely in index.tsx
and all other components will be imported above the initial render function)
Lastly, if we use the function
keyword instead to declare InnerComponent
, then the hoisting kicks in, and it works as seen in the following screenshot.
Example showing that the function keyword causes the function to be hoisted
A Visual Studio Code difference
Now that we have gotten the technical difference out of the way, which I suggest is almost non existing, let’s take a look at a utility difference that I have noticed when using VSC.
VSC allows you to refactor functional components out into new separate files if you have declared them using function
, but not if you have used const
.
gif showing refactoring options of function in VSC
Same function just declared using const
.
gif showing refactoring options of const in VSC
For me, this is actually the most important benefit to using function
instead of const
. Because it removes a tedious step of creating new files and writing boilerplate code.
When this has been said however, the refactoring options (as seen in the second gif) allow you to convert the const
functional expression to a named function, so you can quickly make the switch, especially if you use the keyboard shortcuts.
Subjective benefits (readability)
A last thing to consider is the readability of the syntax. This is of course a subjective matter, and some people prefer the function
syntax whereas others prefer the const
syntax.
One argument that I do like is that the function syntax resembles function declarations of other programming languages the most, and it is therefore easier for non JavaScript developers to understand that syntax compared to the fat arrow syntax.
Final words
My conclusion to this question is that it does not really matter which syntax you use. Just use the one that you prefer. Maybe like me, the difference in VSC could be the determining factor for you. Maybe it is the readability that does it for you? If you have any additions or knowledge about this (maybe I missed something important) then please share it in a comment.
Thanks for reading and have a great day!