Je n'ai commencé que récemment à comprendre ce que sont les macros dans un contexte Lisp. Je crois comprendre que, fondamentalement, le code est exécuté en deux passes. Lors du premier passage, l'interpréteur identifie les appels aux macros et les remplace par leurs valeurs de retour. Deuxièmement, il exécute le code normalement.
Cela ressemble à ce qui se passe avec les hooks personnalisés dans React. Par exemple, si vous avez le crochet useOnlineStatus
:
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; }
C'est comme une macro. Si vous utilisez le crochet useOnlineStatus
comme ceci :
const isOnline = useOnlineStatus();
C'est comme un appel à une macro. Alors si vous avez :
function StatusBar() { const isOnline = useOnlineStatus(); return <h1>{isOnline ? '✅ Online' : '❌ Disconnected'}</h1>; }
Après le premier passage, il est converti en :
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>; }
Ensuite, au deuxième passage, il s'exécutera normalement. Est-ce un modèle précis de ce qui se passe avec les hooks personnalisés ?
Si vous louchez, ça ressemble un peu à ça, mais avec quelques détails :
Bien que les navigateurs effectuent plusieurs passes pour analyser puis exécuter JavaScript, l'appel de hooks n'est pas un tel exemple. Par conséquent, l’exécution du composant ne nécessite qu’une seule passe, s’exécutant ligne par ligne et entrant dans la fonction lorsque l’instruction est rencontrée.
Le même modèle mental peut être appliqué à chaque appel de fonction. Quand vous appelez :
Vous pouvez considérer cela comme décompressant le code dans Math.max et le plaçant dans votre fonction principale. Mais ce n’est pas vraiment comme ça que ça marche.