Closed pcreehan closed 2 years ago
I'm not familiar with the NextJS internals but it may be using React's Fast Refresh. Does #1891 resolve your issue? That isn't part of a public release yet but should be in the nightly
branch.
Experiencing the same. The nightly
branch doesn't solve the issue.
I can reproduce the bug on:
103.0.1
104.0.5112.79
It's not an issue on Chrome 103.0.5060.134-1
.
Also using Next.JS which uses Fast Refresh + SSR hydration.
@drarmstr I tried to debug and compare with the working Chrome version and the difference seems to be in the autoRelease_INTERNAL
function. The timing on when the release function is called seems to have changed. Seems like it's released prematurely resulting in the error.
Digging down the rabbit hole, I found the culprit for Chrome.
Turns out Chrome 104 made it so that useTimeout
works with time of 0. Previously, it was always clamped at 1. Here's the change log. This is the commit hash: 330e7e8111a146e1e69ace46cf07e43943fc75d0
Setting the timeout to 1 in the autoRelease_INTERNAL
function fixes this issue (and is equal to the old behavior).
However, the issue still persists in Firefox. I tested a few older version including v86 and the issue persists. Has this always been an issue? I'm running Firefox, Next.js 12.2.4
, React 18.2.0
and nightly Recoil. Not sure if this happens on older React/Next.js versions since this is the first time I used RecoilSync
(or useRecoilSnapshot
).
I tried tracing _refCount
but I'm not too sure how some parts work. Here's some findings:
useRecoilSnapshot
first renderuseEffect
) added, then remove a count after passing ituseEffect
in useRecoilSnapshot
) (1 -> 2 -> 3 -> 2 -> 1)useRecoilSnapshot
is re-renderedThis is where it starts to differ. Chrome:
useRecoilSnapshot
is re-rendered again useEffect
) (1 -> 2)I'm at a lost at how the count works once the new snapshot become part of the equation. The number does add up if there's 2 different Snapshot instance.
In Firefox, continuing from the first common part:
useRecoilSnapshot
is re-rendered (with 0 count)useEffect
), it tries to retain and spit out the error since there's no more count.I hope that somewhat helps. I'm not too sure how the Snapshot cloning works.
At the end of the day, setting the timeout to a higher number (eg: 10) seems to fix it for Firefox. So I'll be doing that as a fix for now since I've spent a day on this 😂
Ah, thanks for diving into this! There are a few other places with setTimeout() such as in useRecoilSnapshot()
directly. I should be able to update the timeouts to 10 to workaround the FireFox ordering issue..
@Vija02 / @pcreehan - Added workaround in #1943 if you are able to test and confirm?
@Vija02 / @pcreehan - Added workaround in #1943 if you are able to test and confirm?
This seems to fix it from my limited testing. It wasn't hard to repro before and I don't see it occurring with your branch running.
0.7.5 released
I can also confirm that 0.7.5 fixed the issue for me in Firefox. Thanks!
I still have this bug on Firefox (105.0b9). If I set the timeout delay to 100ms it works but I think it will depends of the computer and app performances 😕
Yes, I had to pnpm patch autoRelease_INTERNAL()
function as well with a 100ms timeout to get this working in firefox as well-
Starting last night (8/4/2022), Our DebugObserver component started throwing on
useRecoilSnapshot
with the error that the snapshot has already been released.This reproduces on new versions of browsers only...installing older versions (and testing before they auto-update), we do not get this exception with the exact same code. This is the only place in our code we're using snapshots directly.
I tried reverting to older builds of recoil, running the code on other machines, different browsers, and my coworkers see the same behavior this morning. Our application is build with NextJs...here are our dependencies:
I'd be surprised if we're the only ones experiencing odd new behavior today.
EDIT: I should add that this only repros when running
next dev
but works when runningnext start
. I'm not sure if this implies a problem with nextjs with the new browser update or a problem with Recoil, or something that surfaces only when using Recoil in NextJs.