Since React Hooks, I have decided to let go of React class components. I'm only dealing with hooks and functional components now.
Simple question:
I understand the difference between using an arrow function instead of a regular function inside of a class body. The arrow function would automatically bind (lexical this) to the instance of my class and I don't have to bind it in the constructor. This is nice.
But since I'm not dealing with classes anymore, I would like to know what is the difference of doing the following inside of a functional component:
function App() {
// REGULAR FUNCTION
function handleClick1() {
console.log('handleClick1 executed...');
}
// ARROW FUNCTION
const handleClick2 = () => {
console.log('handleClick2 executed...');
}
return(
<React.Fragment>
<div className={'div1'} onClick={handleClick1}>
Div 1 - Click me
</div>
<div className={'div2'} onClick={handleClick2}>
Div 2 - Click me
</div>
</React.Fragment>
);
}
QUESTION
Both works fine.
Is there a difference in performance? Should I favor one way instead of the other? They're both recreated on every render, correct?
NOTE ON POSSIBLE DUPLICATES
I really don't think this is a duplicate question. I know there are plenty of questions about the difference between arrows and regulars, but I want to know from the perspective of a React functional component and how React handles with it. I've looked around and didn't find one.
CODE SNIPPET FOR TESTING
function App() {
function handleClick1() {
console.log('handleClick1 executed...');
}
const handleClick2 = () => {
console.log('handleClick2 executed...');
}
return(
<React.Fragment>
<div className={'div1'} onClick={handleClick1}>
Div 1 - Click me
</div>
<div className={'div2'} onClick={handleClick2}>
Div 2 - Click me
</div>
</React.Fragment>
);
}
ReactDOM.render(<App/>, document.getElementById('root'));
.div1 {
border: 1px solid blue;
cursor: pointer;
}
.div2 {
border: 1px solid blue;
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
In regular function, arguments will give you list of parameter passed in function, In arrow function arguments is not defined. In regular function, you always have to return any value, but in Arrow function you can skip return keyword and write in single line. In arrow function parameters should be unique.
Unlike regular functions, arrow functions do not have their own this . Arguments objects are not available in arrow functions, but are available in regular functions. Regular functions created using function declarations or expressions are 'constructible' and 'callable'.
Methods like componentWillMount, componentDidUpdate, etc., while functional component doesn't because these are simple JS functions that accept props and return its elements. In contrast, the class component has a render method that extends its Component. However, it had changed when Hooks came to the introduction.
Beside the differences you've already pointed out (lexical scope), arrow functions (and function expressions) are not hoisted, and as such cannot be called before they are defined. See my example. This is in my opinion not a problem, since code that relies on hoisting is much harder to reason about.
React really doesn't care about which one you use (nor can it detect it).
const A = () => {
const name = getName();
function getName() {
return 'praffn';
}
// Will not work
// const getName = () => 'praffn';
return <p>Hi, {name}</p>;
}
ReactDOM.render(<A/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Since you are not accessing the this
context, both will both behave the same.
To understand more, you can check how babel is transpiring to the ECMA:
const handleClick2 = () => {
console.log('handleClick2 executed...');
this.x=3
}
will be transpiled as:
"use strict";
var _this = void 0;
var handleClick2 = function handleClick2() {
console.log('handleClick2 executed...');
_this.x = 3;
};
Link to babel notepad
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With