import type { MutableRefObject } from "react";
import { useState } from "react";
/**
* creates a MutableRef with ref change callback
*
* @example
* const ref = useCallbackRef(0, (newValue, oldValue) => console.log(`${oldValue} -> ${newValue}`));
* ref.current = 1;
* // 0 -> 1
*/
function useCallbackRef<T>(
initialValue: T | null,
callback: (newValue: T | null, lastValue: T | null) => void
): MutableRefObject<T | null> {
const [ref] = useState(() => ({
// value
value: initialValue,
// last callback
callback,
facade: {
get current() {
return ref.value;
},
set current(value) {
const last = ref.value;
if (!Object.is(last, value)) {
ref.value = value;
ref.callback(value, last);
}
}
}
}));
// update callback
ref.callback = callback;
return ref.facade;
}