With the new TNG-Hooks library, JavaScript developers can now decorate regular, standalone functions with useful and frequent stateful and effectful logic, such as querying a remote database or accessing out-of-scope contextual data. The code reuse and composition enabled by Hooks potentially contributes to a smaller, more maintainable and more robust code base.
At last year’s React Conf, React surprised the developer community with React Hooks. With React Hooks, developers could abstract stateful or effectful computations into mere functions, which they would reuse and compose within their React function components. The open source TNG-Hooks introduces the benefits of React Hooks but obviates the dependency on React.
The former approach to adding effects and state to an otherwise functionally pure computation meant abandoning functions in favor of ES Classes. Classes may be more challenging to compose than functions for less experienced developers. Classes may also lead to scattering, and duplicating effectful bits of logic among miscellaneous methods.
To mimic React function components, TNG introduces the concept of Articulated Functions which fulfill two conditions. First, prior to being called, they get wrapped by a TNG decorator. Second, they call hook functions at some point of their execution.
In the following example, the TNG function is the decorator, useState is the hook function, and the function hit is an Articulated Function.
function hit() {
var [count,updateCount] = useState(0);
count++;
updateCount(count);
console.log(`Hit count: ${count}`);
}
hit = TNG(hit);
hit(); // Hit count: 1
hit(); // Hit count: 2
hit(); // Hit count: 3
In the example, the function hit is called several times, returning a different value after each call. This makes hit a stateful function. The useState hook abstracts local state management (retrieval, storage, and update of state). The hook initializes a state variable (count) to 0, returns that variable and a function (updateCount) to update it.
The TNG-Hooks library also provides the useReducer, useEffect, useMemo, useCallback, and useRef hooks, each abstracting a different stateful or effectful computation.
The TNG library additionally provides TNG Custom Hooks, thus mimicking React Custom Hooks. With Custom Hooks, developers can define their own hooks by reusing pre-existing hooks. TNG Custom Hooks are standard JavaScript functions (they are not Articulated Functions), which call, at some point of their execution, Articulated Functions. TNG Custom Hooks must themselves be called from within an Articulated Function:
// a Custom Hook, ***not*** an Articulated Function
function useHitCounter() {
// inherited TNG hooks-context
var [count,updateCount] = useState(0);
count++;
updateCount(count);
return count;
}
// will be TNG(..) Articulated twice, once as
// each button's click handler
function onClick(evt) {
// using a Custom Hook
var hitCount = useHitCounter();
console.log(`Button #${evt.target.id}: ${hitCount}`);
}
var fooBtn = document.getElementById("foo-btn");
var barBtn = document.getElementById("bar-btn");
// each click handler is an Articulated `onClick()`
fooBtn.addEventListener("click",TNG(onClick),false);
barBtn.addEventListener("click",TNG(onClick),false);
This example illustrates a Custom Hook (useHitCounter) which, as required, is not an Articulated Function, and reuses the provided useState hook. useHitCounter itself is used by onClick, which is an Articulated Function. fooBtn and barBtn reuse independently the same stateful custom useHitCounter logic, embedded in the onClick event handler.
While inspired by React, TNG Hooks is a distinct project. Kyle Simpson, the TNG-Hooks library author, explains:
(TNG Hooks) is a separate project with its own motivations and specific behaviors. TNG will remain similar to React Hooks where it makes sense, but there will also be deviations as appropriate.
Just like React Hooks, Articulated Functions and Hooks must respect call rules. At the moment, no mechanism exists to enforce those rules, or warn developers when they infringe the rules. This may lead to erroneous behaviours which are hard to debug. Additionally, React Hooks is a new and experimental technology with dos and don'ts still being ironed out. While TNG Hooks may incorporate lessons learnt from React Hooks, it may also need additional testing to identify best practices and pitfalls.
Installation is available with the tng-hooks npm package and the package touts a test code coverage of 100%.
TNG Hooks is open source software available under the MIT license. Contributions and feedback are encouraged via the TNG-Hooks GitHub project.