Open danielr18 opened 6 years ago
Definitely!
I wonder if you would want an API without a callback so that you could use it in combination with React.useMemo
:
let mutationRecord = useMutationObserver(
document.getElementById("to-observe"),
{ attributes: true },
);
let updateAfterMutations = React.useMemo(handleMutations, [mutationRecord]);
That's another option as well, I think it depends on the usage.
I normally use it to process the mutations once as they occur, and the callback is a good fit for that. Using React.useMemo
would achieve basically the same, except that it would additionally run an equality check on each render, as far as I know.
The good thing I see is that the return value of the hook is more easy to understand, the mutation records vs the result of the MutationObserver's callback.
However, we could modify it so that if no callback is passed, the value will be the mutationRecords, and then you could use React.useMemo
as in your example.
let { value: mutationRecords } = useMutationObserver(
document.getElementById("to-observe"),
{ attributes: true }
);
let updateAfterMutations = React.useMemo(
() => {
// ...
},
[mutationRecord],
);
What do you think?
Came here to suggests useElementResize
(using ResizeObserver
under the hood), and saw this.
We may do something like this:
const useElementResize = ref => {
const [rect, setRect] = React.useState({});
React.useEffect(
() => {
const ro = new ResizeObserver((entries, observer) => {
for (const entry of entries) {
if (entry.target === ref.current) {
// update state if this is our DOM Node
// (we may support multiple refs)
setRect(entry.contentRect);
}
}
});
// observe the passed in ref
ro.observe(ref.current);
return () => {
// cleanup
ro.disconnect();
};
},
[ref] // only update on ref change
);
return rect;
};
Here is a demo if you want to explore
I modified it to always return the callback value, instead of an object.
const defaultCallback = mutationList => mutationList;
function useMutationObserver(targetNode, config, callback = defaultCallback) {
const [value, setValue] = useState(undefined);
const observer = useMemo(
() =>
new MutationObserver((mutationList, observer) => {
const result = callback(mutationList, observer);
setValue(result);
}),
[callback]
);
useEffect(
() => {
if (targetNode) {
observer.observe(targetNode, config);
return () => {
observer.disconnect();
};
}
},
[targetNode, config]
);
return value;
}
Would you be interested to add a
useMutationObserver
hook?My take on the implementation: https://github.com/danielr18/react-hook-mutation-observer/blob/master/index.js