Last active
February 16, 2024 08:34
-
-
Save dounan/00b0c93eeae2e509111faf547ea7f5e1 to your computer and use it in GitHub Desktop.
HOC to HOF analogy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Motivated by https://twitter.com/mjackson/status/885910553432018945 | |
// There are two ways to apply higher-order logic to components. | |
// 1. Use a HOC | |
// 2. Use a generic component that takes a `render` callback. | |
// To illustrate how these work, we will use the the analogy that a | |
// component is just `view = fn(data)`. A HOC can then be simply seen as a | |
// HOF that returns another function (most likely with some partial | |
// application). | |
// Imagine you have a "component" that increments its value. | |
function incrementFn(val) { | |
return val + 1; | |
} | |
// How do you use your increment "component" to render an *array* of items? | |
// ----------------------------------------------------------------------------- | |
// 1. Use a HOC | |
// Define a "HOC" that renders each item in a list with the wrapped "component". | |
// This HOC partially applies the `childFn` to `map`. | |
function mapHOF(childFn) { | |
return array => array.map(childFn); | |
} | |
// Let's wrap it with mapHOF | |
const incrementAllFn = mapHOF(incrementFn); | |
// Final solution: | |
render() { | |
return incrementAllFn([1, 2, 3]); | |
} | |
// ----------------------------------------------------------------------------- | |
// 2. Use a "render" callback | |
// Define a generic component that renders an array with a callback. | |
function mapFn(array, renderFn) { | |
return array.map(renderFn); | |
} | |
// Final solution: | |
render() { | |
return mapFn([1, 2, 3], incrementFn); | |
} | |
// ----------------------------------------------------------------------------- | |
// Both approaches have their own benefits. A big benenfit of using a HOC is | |
// that it hides the implementation details. In the example aboce, the user of | |
// the wrapped `incrementAllFn` doesn't have to know anything about `map`. | |
// However, a big downside of HOC is that in the React world, setting up a HOC | |
// is not trivial: extra component instance, pass through props, pass through | |
// refs, hoisting static methods. | |
// tl;dr - neither approach is strictly better, but remember that HOC is not the | |
// only answer. | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment