Skip to content

[FIX] error occurring in useEffect on hmr/strict mode - #308

Open
PatrykWalach wants to merge 28 commits into
isographlabs:mainfrom
PatrykWalach:fix-use-effect-error-on-hmr-rebase-2
Open

[FIX] error occurring in useEffect on hmr/strict mode#308
PatrykWalach wants to merge 28 commits into
isographlabs:mainfrom
PatrykWalach:fix-use-effect-error-on-hmr-rebase-2

Conversation

@PatrykWalach

@PatrykWalach PatrykWalach commented Jan 6, 2025

Copy link
Copy Markdown
Member

This PR fixes runtime errors thrown during hmr/strict mode.

This on it's own is not enough to make hmr work. Hast to be merged locally with #306 to test hmr.

Rebase of #264

@PatrykWalach
PatrykWalach force-pushed the fix-use-effect-error-on-hmr-rebase-2 branch from 9b897fd to e9d1845 Compare January 6, 2025 23:03

@rbalicki2 rbalicki2 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, just rewrote the comment slightly for grammar and clarity

@rbalicki2 rbalicki2 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I forgot to do a thorough review before accepting 😂 Do we also need this in useUpdatableDisposableState?

If so, there are probably enough places where we do this that it makes sense to have a useEffectIgnoringHmrAndStrictMode hook.

It might return the lastCommittedParentCache, in which case we don't need to do anything extra in useCachedResponsivePreCommitValue

Comment thread libs/isograph-react-disposable-state/src/useCachedResponsivePrecommitValue.ts Outdated
Comment thread libs/isograph-react-disposable-state/src/useLazyDisposableState.ts Outdated
Comment thread libs/isograph-react-disposable-state/src/useDisposableState.ts Outdated
@PatrykWalach

PatrykWalach commented Jan 11, 2025

Copy link
Copy Markdown
Member Author

The solution used here is not good

  • on the first render useEffect will execute (commit and return cleanup)
  • on hmr it will cleanup, then the guard will prevent another execute (commit and return cleanup)

so we end up in a cleaned-up state

The reason it doesn't cause any issues now is probably because of gcBuffer.

@rbalicki2

Copy link
Copy Markdown
Collaborator

Ah yeah, you're totally right. Good call re: gcBuffer. I'm going to think about this. I wonder if we need to try to detect HMR/double mounting more directly.

@PatrykWalach

PatrykWalach commented Jan 13, 2025

Copy link
Copy Markdown
Member Author

on useEffect cleanup we will set itemCleanupPairRef to null, if the component unmounted this has no effect, if it was hmr then cache will once again go through temporaryRetain cycle.

This is not tested. It might be easier to test after merging the second pull request.

@PatrykWalach
PatrykWalach force-pushed the fix-use-effect-error-on-hmr-rebase-2 branch from d3de5d4 to 50f95ea Compare January 13, 2025 20:20
@PatrykWalach

PatrykWalach commented Jan 13, 2025

Copy link
Copy Markdown
Member Author

Now the cycle is

  • commit -> cache is populated
  • cleanup -> set maybeHiddenOrFastRefresh to true, clean up cache
    if component is unmounted, that's the end, if it's hmr:
  • commit -> read maybeHiddenOrFastRefresh and skip cacheItem.permanentRetainIfNotDisposed so there's no error, repopulate cache

so at the end we are in the populated state.

we don't need to set itemCleanupPairRef to null because cleanup runs just before cache is populated which will override itemCleanupPairRef and there are no renders in between.

useUpdatableDisposableState still needs to be fixed and it can't be fixed in the same way, as there's no way to repopulate 🤔

@PatrykWalach
PatrykWalach force-pushed the fix-use-effect-error-on-hmr-rebase-2 branch 2 times, most recently from 4816616 to edeac96 Compare February 1, 2026 08:35
@PatrykWalach PatrykWalach changed the title Fix error occurring in useEffect on hmr Fix error occurring in useEffect on hmr/strict mode Feb 1, 2026
undisposedICIs.current.delete(undisposedICI);
undisposedICI.cleanup();
}
setStateICI(UNASSIGNED_STATE);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's fair to set this to UNASSIGNED_STATE to prevent mutations from firing twice. This was the last piece preventing this PR from being merged @rbalicki2 let me know what you think

Comment thread demos/pet-demo/next.config.js
@PatrykWalach
PatrykWalach force-pushed the fix-use-effect-error-on-hmr-rebase-2 branch 4 times, most recently from e2dd51a to 50bc00f Compare February 1, 2026 14:52
@PatrykWalach
PatrykWalach force-pushed the fix-use-effect-error-on-hmr-rebase-2 branch from 50bc00f to c8e6a67 Compare February 3, 2026 11:10
@PatrykWalach PatrykWalach changed the title Fix error occurring in useEffect on hmr/strict mode Fix: error occurring in useEffect on hmr/strict mode Mar 1, 2026
@PatrykWalach PatrykWalach changed the title Fix: error occurring in useEffect on hmr/strict mode [FIX] error occurring in useEffect on hmr/strict mode Mar 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants