A hook is an array and a counter
The entire mechanism, and once you have seen it the rules of hooks are not rules, they are the only way it could possibly work.
Each component instance gets a list of hook slots and a cursor. Render begins, the cursor resets to zero, and every call to useState takes the next slot and increments. There is no name, no key, no identifier of any kind: the position in the call order is the identity. That is the whole mechanism, and it is about thirty lines.
The rules follow immediately. Call a hook inside an if and the call order changes between renders, so slot two is now the useEffect that used to be slot three, and your state is a dependency array. Call one in a loop whose length varies and the same thing happens with a delay. The rules are not a style guide, they are a consequence, and there is no way to relax them without adding an identifier that would make hooks noisier to write.
This also explains the things people find odd about hooks in React. Why they only work inside a render, why custom hooks compose without any registration, why two components calling the same custom hook get independent state, and why the linter can enforce the rules statically. All of it falls out of "position in call order is the identity".
You should now be able to
- Explain how a hook finds its state across renders
- Derive the rules of hooks from the implementation
Loading…