feat(react): modernize useSyncExternalStore usage for React 18+#1021
Merged
feat(react): modernize useSyncExternalStore usage for React 18+#1021
Conversation
- Drop use-sync-external-store shim; use native useSyncExternalStore from react and inline the with-selector logic (mirrors React's reference implementation). - Remove initializeUseStoreState indirection — no longer needed since React 18+ is the floor (per peerDependencies). - Migrate useLocalStore from raw useState/subscribe to useSyncExternalStore to prevent tearing in concurrent mode. - Add 'use client' banner to ESM and CJS bundles via Rollup so the package works correctly in React Server Components environments (Next.js App Router etc). - Remove use-sync-external-store from runtime dependencies. Refs #1004. Deferred React 18/19 primitive work tracked in #1020.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This was referenced May 4, 2026
ctrlplusb
added a commit
that referenced
this pull request
May 4, 2026
- Drop use-sync-external-store shim; use native useSyncExternalStore from react and inline the with-selector logic (mirrors React's reference implementation). - Remove initializeUseStoreState indirection — no longer needed since React 18+ is the floor (per peerDependencies). - Migrate useLocalStore from raw useState/subscribe to useSyncExternalStore to prevent tearing in concurrent mode. - Add 'use client' banner to ESM and CJS bundles via Rollup so the package works correctly in React Server Components environments (Next.js App Router etc). - Remove use-sync-external-store from runtime dependencies. Refs #1004. Deferred React 18/19 primitive work tracked in #1020.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Refs #1004. Implements the P0 recommendations from the React primitives investigation: drop the
use-sync-external-storeshim, modernizeuseLocalStore, and add the'use client'directive for RSC compatibility.Deferred React 18/19 primitive work (use(), startTransition, useStoreTransition, useStoreDeferredState, useOptimistic, etc.) is tracked separately in #1020.
Changes
src/hooks.js— drop theuse-sync-external-storeshim; use nativeuseSyncExternalStorefromreactand inline the with-selector logic (mirrors React's reference implementation). Remove theinitializeUseStoreStateindirection — no longer needed since React 18+ is the floor (perpeerDependencies).src/use-local-store.js— migrate from rawuseState+subscribetouseSyncExternalStoreto prevent tearing in concurrent mode.src/index.js— remove shim init plumbing.rollup.config.js— add'use client';banner to ESM and CJS outputs so the bundled package works correctly in React Server Components environments (Next.js App Router etc). Rollup strips module-level directives, so the banner is the correct mechanism.package.json— removeuse-sync-external-storefrom runtimedependencies.Notes
isEqualsemantics are preserved exactly (the inlineduseSyncExternalStoreWithSelectoris a direct port of React's reference implementation).eslint-disable react-hooks/exhaustive-depsannotations insrc/hooks.jscover an intentional pattern whereinstis a mutable ref container (not a reactive dependency) — same omission present in upstream React.