I have following custom hook
function useConstant(fn) {
const ref = React.useRef()
if (!ref.current) {
ref.current = fn()
}
return ref.current
}
and it seems quite hard to port this to reasonml, I have to use type cast twice, what's the ideal way?
external toAny: 'a => 'b = "%identity";
external toBool: 'a => bool = "%identity";
let useConstant = (fn: unit => 'a) => {
let ref: React.Ref.t('a) = toAny(React.useRef());
if (!toBool(React.Ref.current(ref))) {
React.Ref.setCurrent(ref, fn());
};
React.Ref.current(ref);
};
If I understand the purpose of the hook correctly, it's really just a reimplementation of
React.useMemo. But for the sake of learning, here's an implementation that should work.It uses the option type, which is specifically designed for cases like this. If there's no value, we represent that using
optionsNonevalue, and if there is a value we useSome. Instead of usingifwith JavaScript's semantically unclear concept of truthiness, we pattern match on theoptionusingswitchto find that it'sNoneand the value needs to be computed, orSometo get at the value.The use of
optionand pattern matching is really common in Reason code, so it's one you should really try to understand using the links provided above for more details if needed.Note that you could also have used
Lazyfor this. But that's far less commonly used and therefore also much less useful to learn.