Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Should not already be working" on window.open in simple React app

I'll post here a heavily simplified version of the webapp I'm working with.

Basically I get an Uncaught Error: Should not already be working. on the window.open(...) line of the following code:

const sleep = milliseconds => new Promise(r => setTimeout(r, milliseconds));
const spawnWind = async () => {
    let newwin = window.open("about:blank", "TEST", "popup,height=260,width=370");
    await sleep(2000);
    newwin.close();
}

useEffect(() => {
    spawnWind()
    .then(() => console.log("After spawnWind"));        
}, []);

This is triggered only on one specific condition: if I access the component which has this code from inside the react app (like from a navbar) and the component has never been mounted before then the error is triggered. In all these other scenarios I have no errors whatsoever:

  • refresh the page after the error is triggered (so, for example, refreshing directly the page when I'm on mysite.com/mycomponent;
  • accessing directly by url (so directly typing mysite.com/mycomponent; this makes perfect sense since it's basically the same as refreshing)
  • accessing the component a second time after having triggered the error on the first access (for example: I access mysite.com, use navbat to navigate to the page with component, the error is triggered. Navigate away with navbar and go back without refreshing then no error is triggered).

I have no idea of what the cause can be. What am I doing wrong?

EDIT: according to the (as the time of writing) open issue on React's GitHub (mentioned in the accepted answer), this is a Firefox-specific issue (locally tested with Chromium, everything works).

like image 764
master_roby3 Avatar asked Oct 25 '25 05:10

master_roby3


1 Answers

Update your code to:

const sleep = milliseconds => new Promise(r => setTimeout(r, milliseconds));

const spawnWind = async () => {
  let newwin = window.open("about:blank", "TEST", "popup,height=260,width=370");
  await sleep(2000);
  newwin.close();

  console.log("After spawnWind")
}

useEffect(() => {
  setTimeout(spawnWind, 0)
}, []);

This is an open bug in react about this issue.

The issue is because of the blocking call window.open within the useState hook, which messes with React's synchronisation of the state.

The only solution so far is to wrap the blocking calls inside a setTimeout(): using a delay of 0, as stated in the documentation, executes the code passed to setTimeout in the next event cycle, allowing pending rendering to finish (check the issue mentioned above).

like image 119
Robin Thomas Avatar answered Oct 26 '25 20:10

Robin Thomas



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!