react-use icon indicating copy to clipboard operation
react-use copied to clipboard

[request]Mutation Observer API

Open devvit opened this issue 5 years ago • 2 comments
trafficstars

Is your feature request related to a problem? Please describe. There should be three modern observers: Intersection Observer API => useIntersection ☑️ Resize Observer API => useMeasure ☑️ Mutation Observer API => useMutation ✖️

Describe the solution you'd like


useMutation(wrapper, options, () => {})
// OR
[wrapper] = useMutation(options, () => {})

<A ref={wrapper}></A>

devvit avatar May 10 '20 03:05 devvit

Possible reference: https://vueuse.org/core/usemutationobserver/#usemutationobserver

vincerubinetti avatar Nov 04 '22 02:11 vincerubinetti

For reference, this is my current implementation.

This implementation follow useIntersection API design.

useMutationObserver

import type { RefObject } from "react";
import { useEffect, useState } from "react";

export function useMutationObserver<T extends Node>(
  ref: RefObject<T>,
  options: MutationObserverInit
) {
  const [mutations, setMutations] = useState<MutationRecord[]>();

  useEffect(() => {
    if (!ref.current || typeof MutationObserver !== "function") {
      return () => {};
    }

    const handler = (mutations: MutationRecord[]) => setMutations(mutations);
    const observer = new MutationObserver(handler);
    observer.observe(ref.current, options);

    return () => {
      setMutations(undefined);
      observer.disconnect();
    };
  }, [ref, options]);

  return mutations;
}

Example Usage

  const messageEl = useRef<HTMLUListElement>(null);
  const mutations = useMutationObserver(messageEl, {
    childList: true,
    subtree: true,
  });
  useEffect(() => {
    const target = messageEl.current;
    
    // if any update in the message list, scroll to the latest message
    if (mutations && target) {
      window.scroll({ top: target.scrollHeight, behavior: "smooth" });
    }
  }, [mutations]);

kayac-chang avatar Mar 21 '23 13:03 kayac-chang