我在尝试将第三方产品巡更(Intercom(与react应用程序集成时遇到了一个问题。没有办法以编程的方式结束我发现的一次旅行。
基本上,我需要一个道具,无论某个非react DOM元素是否存在,它都可以在react应用程序中更改。我需要能够在钩子或componentDidUpdate
中判断DOM中是否存在某个非React元素。
我不知道该怎么办,因为很明显,当这次巡演开始和结束时,就反应而言,状态或道具都没有变化。
有没有一种方法可以将document.getElementById("Id-of-the-product-tour-overlay")
之类的结果作为道具来包装组件?有没有办法让我用钩子看着它?
理想情况下类似
componentDidUpdate(){
if(elementExists){
//Do stuff that needs to happen while tour is on
}
if(!elementExists){
//do app stuff to end the tour
}
}
//OR
useEffect(()=>{
//do stuff conditional on element's existence
},[elementExists])
实现这一点的简单方法是准备一个函数,该函数接收HTML元素,并返回一个函数作为参数接收回调(返回其他函数的函数-currying for pure(。返回函数的结果是一个带有回调集的新MutationObserver。
const observeTarget = target => callback => {
const mutationObserver = new MutationObserver(callback);
mutationObserver.observe(target, { childList: true });
}
在非反应文件中,您可以向该函数提供一个HTML元素,该元素是您想要调查的第三方元素的容器。
然后导出函数,就可以在react组件中使用它。
export const observeProductTourOverlay = observeTarget(containerOfProductTourOverlay);
然后在React组件中,您可以使用useEffect挂钩并使用功能
const checkIFMyCompExists = () => !!document.querySelector("#my-component");
export const FromOutside = () => {
const [elementExists, setElementExist] = useState(checkIFMyCompExists());
const [indicator, setIndicator] = useState(3);
useEffect(() => {
observeProductTourOverlay((mutationRecord, observer) => {
const doesExist = checkIFMyCompExists();
setElementExist(doesExist);
// this will fire every time something inside container changes
// (i.e. a child is added or removed)
});
// garbage collector should take care of mutationObserver in a way there are no memory leaks, so no need to disconnect it on compoment unmouting.
}, []);
useEffect(() => {
setIndicator(elementExists);
//do stuff when elementExistance changes
}, [elementExists]);
return (
<div>
<div>{"my component has been added: " + indicator}</div>
</div>
);
};
在此处查找工作演示:https://codesandbox.io/s/intelligent-morning-v1ndx
你能使用while循环吗?
useEffect(()=>{
while (document.getElementById('theTour') !== null) {
// do stuff
}
// do cleanup
})