React useMutationObserver钩子

使用MutationObserver监听DOM树的变化

  • 使用useEffect()钩子,依赖于callbackoptions的值。
  • 检查给定的ref是否已初始化。如果是,则创建一个新的MutationObserver并将其传递给callback
  • 使用给定的options调用MutationObserver.observe()来监视给定的ref的变化。
  • 在组件卸载时使用MutationObserver.disconnect()将观察者从ref中移除。
const useMutationObserver = (
  ref,
  callback,
  options = {
    attributes: true,
    characterData: true,
    childList: true,
    subtree: true,
  }
) => {
  React.useEffect(() => {
    if (ref.current) {
      const observer = new MutationObserver(callback);
      observer.observe(ref.current, options);
      return () => observer.disconnect();
    }
  }, [callback, options]);
};

const App = () => {
  const mutationRef = React.useRef();
  const [mutationCount, setMutationCount] = React.useState(0);
  const incrementMutationCount = () => {
    return setMutationCount(mutationCount + 1);
  };
  useMutationObserver(mutationRef, incrementMutationCount);
  const [content, setContent] = React.useState('Hello world');

  return (
    <>
      <label htmlFor="content-input">编辑此处以更新文本:</label>
      <textarea
        id="content-input"
        style={{ width: '100%' }}
        value={content}
        onChange={e => setContent(e.target.value)}
      />
      <div
        style={{ width: '100%' }}
        ref={mutationRef}
      >
        <div
          style={{
            resize: 'both',
            overflow: 'auto',
            maxWidth: '100%',
            border: '1px solid black',
          }}
        >
          <h2>调整大小或更改内容:</h2>
          <p>{content}</p>
        </div>
      </div>
      <div>
        <h3>变化次数 {mutationCount}</h3>
      </div>
    </>
  );
};

ReactDOM.createRoot(document.getElementById('root')).render(
  <App />
);