I’ve just recently started to learn about what a macro is in the context of Lisp. My understanding is that, basically, the code is executed in two passes. On the first pass, the interpreter identifies calls to macros and replaces them with their return value. On the second, it executes the code normally.
This seems like what is happening with custom hooks in React. For example, if you have a useOnlineStatus hook:
function useOnlineStatus() {
const [isOnline, setIsOnline] = useState(true);
useEffect(() => {
function handleOnline() {
setIsOnline(true);
}
function handleOffline() {
setIsOnline(false);
}
window.addEventListener('online', handleOnline);
window.addEventListener('offline', handleOffline);
return () => {
window.removeEventListener('online', handleOnline);
window.removeEventListener('offline', handleOffline);
};
}, []);
return isOnline;
}
that’s like a macro. And if you use that useOnlineStatus hook like so:
const isOnline = useOnlineStatus();
it’s like a call to a macro. So if you have:
function StatusBar() {
const isOnline = useOnlineStatus();
return <h1>{isOnline ? '✅ Online' : '❌ Disconnected'}</h1>;
}
after the first pass it gets transformed into:
function StatusBar() {
const [isOnline, setIsOnline] = useState(true);
useEffect(() => {
function handleOnline() {
setIsOnline(true);
}
function handleOffline() {
setIsOnline(false);
}
window.addEventListener('online', handleOnline);
window.addEventListener('offline', handleOffline);
return () => {
window.removeEventListener('online', handleOnline);
window.removeEventListener('offline', handleOffline);
};
}, []);
return <h1>{isOnline ? '✅ Online' : '❌ Disconnected'}</h1>;
}
and then on the second pass it gets executed normally. Is that an accurate model of what’s going on with custom hooks?
>Solution :
If you squint it’s kind of like that, but a couple things:
-
While the browser does do multiple passes to parse and then execute javascript, calling a hook is not an example of that. So running the component is just a single pass, going line by line, and stepping into the function when it hits that instruction.
-
The same mental model could be applied to every function call. When you call:
const foo = Math.max(0, 5);
You could think of that as unpacking the code that’s in Math.max and putting it into your main function. But it’s not literally doing that.