Hooks beyond React
Playing with hooks outside React realm
It’s been a while since React team released hooks, at the moment of writing this article they’re still officially experimental™ but to be officially official™ the next day .. timing is my middle name.
React used classes to represent a component for years, arguably classes are a good representation of components since they can have properties, methods, constructors… But the point of using React is to write the UI as a function of state by declaratively composing its elements, thus the focus on functional programming, purity and immutability.
With all that and the hate on ES6 classes, React team later introduced functional components. With this new tool you can write components as pure functions of props and state with no side-effects. The catch is you often need side-effects, so you find yourself starting happily with a pure clean functional component, just to downgrade it later into the lowest form of life possible.
React hooks is the long-awaited upgrade to functional components. Hooks brilliantly added side-effects to functional components, bringing everything good about classes to functions along with the nostalgic mixins.
When you think carefully about hooks, at their core they are simply a tool to allow side-effects in pure functions. So you can still write a beautiful UI = f(state) while having all the nasty side-effects in there as well, so I was wondering if we can do the same outside React?
Functional code is beautiful, but the world being imperfect forces side-effects in our code. When you mix the two things get tricky with promises and such, so what if we could solve some cases with hooks?
The least I can say about hooks is they are magical, I had no idea how this was done until the first rule of hooks gave it up. The rule being “never use hooks in conditional blocks”, so the trick is they keep track of invocation order. I played with the idea and managed to build quick hideous hooks:
The code is straightforward:
- getToTheTop is a handy function to get to the component function, we simply skip all the hooks (functions starting with ‘use’) to the top
- useInitHooks, useEndHooks aren’t needed in React because that’s handled outside the components probably, but we need those here to initiate some inner mechanisms and detect when it’s a first run or later runs
- useHook registers a hook at an index, if you want a thorough explanation check Rudi Yardley’s great article
- useState and useEffect to test the implementation
Now time to test it, I came up with a simple example:
Which results in:
Here we go
New pair (0, 1)
New pair (1, 2)
New pair (3, 4)
New pair (5, 6)
New pair (7, 8)
5 unique pairs found
Result is [ 1, 3, 3, 7, 11, 11, 15 ]
Even though sum is a pure function (not actually sum but the resulting function), we managed to use useEffect to log a message at the first run, then watch pair changes and keep count of unique pairs using the state provided by useState.
component.unmount() allows to run destruction process, to unregister any listeners etc., this is handled by the renderer in React but in our case had to be done manually.
Conclusion
This is an early proof of concept, it might not be the ultimate solution to side-effects. Honestly hooks are so perfect for components that it’s hard to think outside that box. Nonetheless, this might be a viable solution to problems that could be modeled as a tree of subproblems in a similar way to a React tree. I’m still digging deeper trying to find such scenarios, if you have any suggestions feel free to share.
Happy hooks day !