React ES6 Arrow Functions
Arrow functions offer shorter syntax and, crucially, lexically bind 'this' — which is why React code leans on them so heavily.
Arrow function syntax
Arrow functions, introduced in ES6, provide a compact alternative to the 'function' keyword. Parentheses around a single parameter are optional, a single expression body is returned implicitly without the 'return' keyword, and a block body with braces behaves like a normal function body.
Arrow function variations
function App() {
// Traditional function
function double(n) {
return n * 2;
}
// Arrow function, block body
const doubleArrow = (n) => {
return n * 2;
};
// Arrow function, implicit return
const doubleShort = (n) => n * 2;
// Single parameter, parens optional
const square = n => n * n;
// No parameters
const getRandom = () => Math.random();
// Returning an object literal needs parentheses
const makePoint = (x, y) => ({ x, y });
console.log(
double(4),
doubleArrow(4),
doubleShort(4),
square(4),
getRandom(),
makePoint(1, 2)
);
return (
<div>
<p>double(4) = {double(4)}</p>
<p>doubleArrow(4) = {doubleArrow(4)}</p>
<p>doubleShort(4) = {doubleShort(4)}</p>
<p>square(4) = {square(4)}</p>
<p>makePoint(1, 2) = {JSON.stringify(makePoint(1, 2))}</p>
</div>
);
}
export default App;
Lexical 'this': the real reason React uses them
A regular function creates its own 'this' binding depending on how it's called, which is what causes event handlers in class components to lose track of their instance. An arrow function has no 'this' of its own — it captures 'this' from the surrounding scope where it was defined, and that binding never changes no matter how the arrow function is later invoked.
Why arrow functions fix 'this' in classes
import React from 'react';
class Timer extends React.Component {
state = { seconds: 0 };
// Arrow function class field: `this` is captured from Timer's instance
tick = () => {
this.setState((prev) => ({ seconds: prev.seconds + 1 }));
};
componentDidMount() {
this.intervalId = setInterval(this.tick, 1000);
}
componentWillUnmount() {
clearInterval(this.intervalId);
}
render() {
return <p>Seconds elapsed: {this.state.seconds}</p>;
}
}
export default Timer;
If 'tick' were written with the 'function' keyword instead, calling it via setInterval would invoke it with 'this' set to undefined (in strict mode) rather than the Timer instance, and 'this.setState' would throw.
Arrow functions in function components
Function components don't have a 'this' problem since Hooks replaced classes, but arrow functions are still everywhere in modern React — for inline event handlers, for callbacks passed to array methods like .map(), and for the component definitions themselves.
Arrow functions in everyday React code
function ProductList({ products, onSelect }) {
return (
<ul>
{products.map((product) => (
<li key={product.id} onClick={() => onSelect(product.id)}>
{product.name}
</li>
))}
</ul>
);
}
function App() {
const products = [
{ id: 1, name: 'Keyboard' },
{ id: 2, name: 'Mouse' },
{ id: 3, name: 'Monitor' },
];
function handleSelect(id) {
console.log('Selected product', id);
}
return <ProductList products={products} onSelect={handleSelect} />;
}
export default App;
- Arrow functions cannot be used as constructors — `new MyArrow()` throws a TypeError.
- Arrow functions have no 'arguments' object; use rest parameters (...args) instead.
- Arrow functions cannot be generator functions (no `function*` equivalent).
- Arrow functions do not have their own 'this', 'super', or 'new.target' bindings.
Exercise: React ES6 Arrow Functions
What value of `this` does an arrow function use inside a class method?