4

If I keep observe inside setTimeout then updateChild called on 1st render, but if I removed setTimeout then it works on every render. Could someone please help me how to solve this problem as I need the setTimeout?

private observer = new MutationObserver(this.updateChild.bind(this));

updateChild(mutationsList: MutationRecord[], observer: MutationObserver) {
    console.log('updated');
  }

handelMouseEnter(){
      if (this.popupTimer) {
        clearTimeout(this.popupTimer);
      }
      this.popupTimer = setTimeout(() => {
        this.container = document.createElement('div');
        document.body.appendChild(this.container);

        ReactDOM.render(
          <Layout innerRef={e => (this.myRef = e)}>{this.props.children}</Layout>,
          this.container,
        );

        if (this.myRef) {
          this.observer.observe(this.myRef, { childList: true });
        }
   }, 500);
}
Sanjan
  • 49
  • 4
  • 3
    Can you add the entire class at least? – Konrad Aug 28 '22 at 22:31
  • Two immediate things I see. First, looks like you're rendering a new react tree from within a component rendered with react? I'd suggest using a [portal](https://reactjs.org/docs/portals.html) and render it like any other child component. Just have a `showPortal` boolean in state, and set this to true in the setTimeout. Then render the portal or not based on that. Doing this would resolve my second worry about `this.myRef` being populated immediately after the render call which. You'd just move that to `componentDidMount`. – AlienWithPizza Sep 01 '22 at 06:13

2 Answers2

1

A MutationObserver fires its callback as many times whether declared inside or outside a setTimeout callback.

Example (JSBin demo) :

const paragraphElement = document.querySelector('p');
// Update body with current time every second, which will trigger MutationObserver
setInterval(() => {
    paragraphElement.textContent = new Date().toLocaleString();
}, 1000);
// Create a MutationObserver outside setTimeout
new MutationObserver(() => console.log(`Outside setTimeout : ${paragraphElement.textContent}`))
    .observe(paragraphElement, { childList: true });
// Create a MutationObserver inside setTimeout
setTimeout(
    () => new MutationObserver(() => console.log(`Inside setTimeout : ${paragraphElement.textContent}`))
        .observe(paragraphElement, { childList: true }),
    500
);
KaKi87
  • 915
  • 7
  • 15
0

Without the rest of what's all going on I cannot be sure of the problem. I setup a sandbox with my suggestion around moving to using a portal.

I'm not sure what mutations you are looking to observe, so I setup 2 example portals (Portal1.tsx/Portal2.tsx). You can swap between them by changing the import in Div.tsx.

** I know this does not at all give a pinpointed, what is not working in your current solution, but maybe is a working example of what you're attempting to do?

AlienWithPizza
  • 386
  • 1
  • 8