Functions are everywhere in React. Event handlers, callbacks, array operations, effects, custom hooks, and component logic all depend on JavaScript functions.
1 Functions Are First-Class Values
JavaScript allows functions to be stored in variables, passed as arguments, and returned from other functions.
function greet(name) {
return `Hello ${name}`;
}
const fn = greet;
console.log(fn("Rahul"));
2 Callback Functions
A callback is a function passed to another function so that it can be called later or during an operation.
function processOrder(order, callback) {
console.log("Processing order");
callback(order);
}
processOrder(
{ id: 101 },
order => {
console.log("Completed:", order.id);
}
);
3 Callbacks in React
React event handlers are commonly callback functions.
function SaveButton() {
function handleSave() {
console.log("Saved");
}
return (
<button onClick={handleSave}>
Save
</button>
);
}
React keeps the function and calls it when the event occurs.
4 Passing a Callback to a Child
function Parent() {
function handleMessage(message) {
console.log(message);
}
return (
<Child onMessage={handleMessage} />
);
}
function Child({ onMessage }) {
return (
<button
onClick={() =>
onMessage("Hello Parent")
}
>
Send Message
</button>
);
}
5 What Is a Closure?
A closure happens when a function remembers variables from the surrounding lexical scope even after the outer function has finished executing.
function createCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
The returned function remembers the count variable. That remembered environment is the important part of the closure.
6 Closure Flow
flowchart TD
A[Outer Function] --> B[Local Variable]
A --> C[Inner Function]
B --> C
C --> D[Returned Function]
D --> E[Remembers Outer Variable]
7 Closures in React
React function components create closures. Event handlers can access values from the render in which those handlers were created.
function Counter() {
const [count, setCount] = useState(0);
function handleClick() {
console.log("Current render count:", count);
setCount(count + 1);
}
return (
<button onClick={handleClick}>
Count: {count}
</button>
);
}
The event handler closes over the variables available to that render.
8 Stale Closure Concept
A stale closure can happen when a callback keeps an older value than you expected. This is especially important when working with asynchronous code, timers, or effects.
function Counter() {
const [count, setCount] = useState(0);
function increaseLater() {
setTimeout(() => {
setCount(count + 1);
}, 1000);
}
return (
<button onClick={increaseLater}>
Count: {count}
</button>
);
}
When the update depends on the previous state, the functional updater is safer:
setTimeout(() => {
setCount(previous => previous + 1);
}, 1000);
9 Function Scope
Variables declared inside a function are normally available only within that function and its nested functions.
function createMessage() {
const message = "Hello";
function printMessage() {
console.log(message);
}
printMessage();
}
10 Arrow Functions
Arrow functions are commonly used in React.
const add = (a, b) => a + b;
const users = [
{ id: 1, name: "Rahul" },
{ id: 2, name: "Priya" }
];
const names = users.map(
user => user.name
);
11 Function as a Prop
Passing a function as a prop allows a child to notify its parent about an action.
flowchart TD
A[Parent Creates Function] --> B[Pass Function As Prop]
B --> C[Child Receives Callback]
C --> D[User Performs Action]
D --> E[Child Calls Callback]
E --> F[Parent Handles Action]
12 Complete Example
function SearchPage() {
const [search, setSearch] = useState("");
function handleSearch(value) {
setSearch(value);
}
return (
<div>
<SearchBox
value={search}
onSearch={handleSearch}
/>
<p>Searching for: {search}</p>
</div>
);
}
function SearchBox({ value, onSearch }) {
return (
<input
value={value}
onChange={event =>
onSearch(event.target.value)
}
/>
);
}
13 Common Mistakes
- Calling a callback during render instead of passing the function.
- Not understanding that callbacks can close over values from a render.
- Ignoring stale closure problems in asynchronous code.
- Mutating captured objects instead of using predictable state updates.
- Confusing a function reference with the result of calling a function.
14 Interview Questions
- What is a callback function?
- What is a closure?
- Why are closures important in React?
- What is a stale closure?
- Why can a setTimeout callback see an older state value?
- Why do React developers pass functions as props?
- What is the difference between
onClick={handleClick}andonClick={handleClick()}?
15 Key Takeaways
- Functions are first-class values in JavaScript.
- Callbacks are functions passed to other functions.
- Closures allow functions to remember surrounding variables.
- React event handlers and callbacks commonly use closures.
- Functional state updates help when asynchronous callbacks depend on previous state.
Conclusion
Closures and callbacks are not advanced React-only concepts. They are JavaScript fundamentals that explain a lot of React behavior. Understanding them makes event handlers, effects, timers, callbacks, and component communication much easier to reason about.