简体   繁体   English

ReactJS - 使用 Mutation Observer 检测第三方 DOM 插入

[英]ReactJS - Detect third-party DOM insert using Mutation Observer

Inside the component, a third-party JavaScript library has injected some content into a specific DIV ( voice-service ) after React render.在组件内部,第三方 JavaScript 库在 React 渲染后将一些内容注入到特定的 DIV( voice-service )中。 I wanted to add or remove some CSS class on that DIV ( voice-service ) when the DOM was injected using Mutation Observer, like -当使用 Mutation Observer 注入 DOM 时,我想在该 DIV( voice-service )上添加或删除一些 CSS 类,例如 -

When DOM injected -当 DOM 注入时 -

<div id="maxVoiceContainer" class="voice-service service--active">
 // third-party content
</div>

When DOM Not injected -当 DOM 未注入时 -

<div id="maxVoiceContainer" class="voice-service service--inactive">
// third-party content
</div>

heroVoice Component:英雄语音组件:

import React, { useRef, useState, useEffect } from 'react';

const heroVoice = (props) => {

    const elementRef = useRef();
    const [voiceAvailability, setVoiceAvailability] = useState(false);

    useEffect(() => {
        const config = { attributes: false, characterData: false, childList: true, subtree: true, attributeOldValue: false, characterDataOldValue: false };
        const observer = new MutationObserver(mutations => {
            mutations.forEach(mutation => {
                const newNodes = mutation.addedNodes;
                newNodes.forEach(node => {
                    if (node.classList && node.classList.contains('pocket-sphinx-container')) {
                        setVoiceAvailability(status => !status);
                    }
                });
            });
        });
        observer.observe(elementRef.current, config);
    }, []);

    return (
        <div
            ref={elementRef}
            id="maxVoiceContainer"
            className={`voice-service ${voiceAvailability ? ' service--active' : 'service--inactive'}`}
        >
          // third-party content
        </div>
    );
}

export default heroVoice;

Wanted to know -想知道 -

  1. Do I need to disconnect the observer?我需要断开观察者的连接吗?
  2. Looks good?看起来不错? best practices?最佳实践?
  3. Also, I do not want to re-render when the state was updated!另外,我不想在状态更新时重新渲染!

Q: Do I need to disconnect the observer?问:我需要断开观察者的连接吗? It's not needed directly, but I recommand it with the mutationObserver.disconnect() Method, because you is called One time on ComponentDidMount.它不是直接需要的,但我推荐使用mutationObserver.disconnect()方法,因为你在 ComponentDidMount 上被调用一次。 An empty Array at the second parameter means it.第二个参数处的空数组表示它。 Ref 参考

Looks good?看起来不错? best practices?最佳实践? Yes looks quite good.是的,看起来不错。 Avoid nested forEach.避免嵌套 forEach。 Better use first a map and than an forEach最好先使用地图而不是 forEach

 mutations.map(mutation => mutation.addedNodes).forEach(node => { if (node.classList && node.classList.contains('pocket-sphinx-container')) { setVoiceAvailability(status => !status); } });

Also, I do not want to re-render when the state was updated!另外,我不想在状态更新时重新渲染! React's lifecycle is build for this. React 的生命周期就是为此而构建的。 There are two possibilities.有两种可能。 First, you can use Redux or you make a local variable which is being setted in the forEach.首先,您可以使用 Redux 或创建一个在 forEach 中设置的局部变量。 But generally don't use a setState hook in a forEach但一般不要在 forEach 中使用 setState 钩子

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM