Inside the component, a third-party JavaScript library has injected some content into a specific DIV ( voice-service
) after React render. I wanted to add or remove some CSS class on that DIV ( voice-service
) when the DOM was injected using Mutation Observer, like -
When DOM injected -
<div id="maxVoiceContainer" class="voice-service service--active">
// third-party content
</div>
When DOM Not injected -
<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 -
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. An empty Array at the second parameter means it. Ref
Looks good? best practices? Yes looks quite good. Avoid nested forEach. Better use first a map and than an 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. There are two possibilities. First, you can use Redux or you make a local variable which is being setted in the forEach. But generally don't use a setState hook in a forEach
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.