Skip to content

fix(hooks): align useIsMobile with the react-hooks/set-state-in-effect#10927

Open
denis-shvets wants to merge 1 commit into
shadcn-ui:mainfrom
denis-shvets:use-mobile
Open

fix(hooks): align useIsMobile with the react-hooks/set-state-in-effect#10927
denis-shvets wants to merge 1 commit into
shadcn-ui:mainfrom
denis-shvets:use-mobile

Conversation

@denis-shvets

@denis-shvets denis-shvets commented Jun 11, 2026

Copy link
Copy Markdown

Replaces the setState in useEffect pattern with useSyncExternalStore, React 19's prescribed API for mirroring browser/external state into React. This resolves the hard lint error introduced by the react-hooks/set-state-in-effect rule in eslint-config-next 16.2.5+ and makes the hook compile cleanly under the React 19 Compiler.

ℹ️ No public interface changes. No extra logic added. Drop-in replacement for all callers.

  • Eliminates boolean | undefined flicker - getSnapshot returns a real boolean on the first client render, no undefined intermediate state
  • SSR-safe via getServerSnapshot returning false
  • Tear-free under concurrent rendering (useSyncExternalStore guarantee)
  • Applied to all four hook copies: apps/v4/hooks and the three registry bases (base, radix, new-york-v4); registry JSON rebuilt accordingly

Fixes: #8739

@vercel

vercel Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

@denis-shvets is attempting to deploy a commit to the shadcn-pro Team on Vercel.

A member of the Team first needs to authorize it.

@denis-shvets

Copy link
Copy Markdown
Author

@shadcn could you take a quick look at this when you get a chance?

Replaces the setState-in-effect pattern with useSyncExternalStore, React 19's prescribed API for mirroring browser/external state into React. This resolves the hard lint error introduced by the react-hooks/set-state-in-effect rule in eslint-config-next 16.2.5+ and makes the hook compile cleanly under the React 19 Compiler.

No public interface changes — drop-in replacement for all callers.

- Eliminates boolean | undefined flicker — getSnapshot returns a real boolean on the first client render, no undefined intermediate state
- SSR-safe via getServerSnapshot returning false
- Tear-free under concurrent rendering (useSyncExternalStore guarantee)
- Applied to all four hook copies: apps/v4/hooks and the three registry bases (base, radix, new-york-v4); registry JSON rebuilt accordingly
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.

[bug]: setIsMobile is called synchronously in useIsMobile and breaks new react-hooks/set-state-in-effect eslint rule

1 participant