Skip to content

fix: use useSyncExternalStore in withUniwind for better compatibility with react lifecycle - #657

Merged
Brentlok merged 2 commits into
mainfrom
refactor/use-useSyncExternalStore
Sep 1, 2026
Merged

fix: use useSyncExternalStore in withUniwind for better compatibility with react lifecycle#657
Brentlok merged 2 commits into
mainfrom
refactor/use-useSyncExternalStore

Conversation

@Brentlok

@Brentlok Brentlok commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

#649

Summary by CodeRabbit

  • Bug Fixes

    • Improved theme, CSS variable, class-style, and color updates after suspended content is revealed.
    • Ensured wrapped components consistently reflect the latest styling state across native and web platforms.
  • Tests

    • Added coverage for theme and styling updates across suspended React trees on native and web.

@coderabbitai

coderabbitai Bot commented Sep 1, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Team

Run ID: c338e036-b454-4980-81d9-e88a46f04563

📥 Commits

Reviewing files that changed from the base of the PR and between 0a05375 and b061189.

📒 Files selected for processing (7)
  • packages/uniwind/src/core/listener.ts
  • packages/uniwind/src/core/web/cssListener.ts
  • packages/uniwind/src/hoc/withUniwind.native.tsx
  • packages/uniwind/src/hoc/withUniwind.tsx
  • packages/uniwind/tests/native/components/scoped-theme.test.tsx
  • packages/uniwind/tests/native/hoc/freeze.test.tsx
  • packages/uniwind/tests/web/hoc/freeze.test.tsx
💤 Files with no reviewable changes (1)
  • packages/uniwind/tests/native/components/scoped-theme.test.tsx

Included review availability: Your plan provides up to 4 included reviews per hour; 3 remain after this review.


📝 Walkthrough

Walkthrough

The change replaces manual HOC rerender subscriptions with useSyncExternalStore. Listeners now expose revision-based snapshots, and native and web tests verify updates after suspended trees are revealed.

Changes

External store updates

Layer / File(s) Summary
Revision and CSS snapshots
packages/uniwind/src/core/listener.ts, packages/uniwind/src/core/web/cssListener.ts
UniwindListenerBuilder tracks dependency revisions and exposes getSnapshot. CSSListenerBuilder combines theme, variable, and media-query states into a snapshot.
HOC external-store subscriptions
packages/uniwind/src/hoc/withUniwind.native.tsx, packages/uniwind/src/hoc/withUniwind.tsx
Native HOCs use useDependencies, and web HOCs use useClassNames. Both shared hooks use useSyncExternalStore.
Suspended-tree validation
packages/uniwind/tests/native/components/scoped-theme.test.tsx, packages/uniwind/tests/native/hoc/freeze.test.tsx, packages/uniwind/tests/web/hoc/freeze.test.tsx
New native and web tests verify theme, variable, class, color, and wrapped-component updates after Suspense reveals a tree. The previous scoped-theme test was removed.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to b0611

The PR improves theme and style update handling for suspended native and web React trees. No actionable merge-blocking risk remains at the current head beyond normal checks and review.

Sequence Diagram(s)

sequenceDiagram
  participant SuspendedTree
  participant React
  participant UniwindListener
  participant CSSListener
  participant HOC
  SuspendedTree->>React: suspend rendering
  React->>HOC: retain external-store subscription
  UniwindListener-->>React: publish updated dependency snapshot
  CSSListener-->>React: publish updated class-name snapshot
  React->>HOC: re-render after tree reveal
  HOC-->>SuspendedTree: apply updated theme and styles
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: replacing the existing withUniwind subscription approach with useSyncExternalStore to improve React lifecycle compatibility.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 6…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 6 files.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/use-useSyncExternalStore

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Sep 1, 2026

Copy link
Copy Markdown

Greptile Summary

The PR migrates withUniwind subscriptions from layout-effect-driven reducer updates to React external-store subscriptions so suspended trees can catch up with styling changes.

  • Adds revision-based snapshots for native style dependencies.
  • Adds theme, variable, and media-query snapshots for web class names.
  • Adds native and web Suspense lifecycle coverage for automatic and manual HOCs.

Confidence Score: 5/5

The PR appears safe to merge, with no concrete changed-code correctness or security failures identified.

The new snapshots change whenever a currently subscribed native dependency, web theme or variable revision, or relevant media-query match changes, allowing React to reconcile updates missed while a subtree was suspended.

Important Files Changed

Filename Overview
packages/uniwind/src/core/listener.ts Adds monotonic per-dependency revisions and snapshot access for native external-store consumers.
packages/uniwind/src/core/web/cssListener.ts Adds a stable snapshot combining theme and variable revisions with relevant media-query states.
packages/uniwind/src/hoc/withUniwind.native.tsx Replaces layout-effect subscriptions with dependency-keyed useSyncExternalStore callbacks.
packages/uniwind/src/hoc/withUniwind.tsx Replaces web HOC effect subscriptions with class-name-keyed external-store subscriptions.
packages/uniwind/tests/native/hoc/freeze.test.tsx Verifies native hooks and HOCs catch up with theme changes after a suspended subtree is revealed.
packages/uniwind/tests/web/hoc/freeze.test.tsx Verifies equivalent suspended-tree recovery for web hooks, wrappers, and mapped props.

Sequence Diagram

sequenceDiagram
    participant Runtime as Uniwind runtime
    participant Listener as Platform listener
    participant React as useSyncExternalStore
    participant HOC as withUniwind component
    Runtime->>Listener: Update theme, variables, or media query
    Listener->>Listener: Advance/read snapshot
    Listener-->>React: Notify subscriber
    React->>Listener: Read latest snapshot
    React->>HOC: Re-render with current styles
    Note over React,HOC: Suspended trees compare snapshots when revealed
Loading

Reviews (1): Last reviewed commit: "test: extend freeze tests" | Re-trigger Greptile

@Brentlok
Brentlok merged commit af5f834 into main Sep 1, 2026
3 checks passed
@Brentlok
Brentlok deleted the refactor/use-useSyncExternalStore branch September 1, 2026 07:19
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

🚀 This pull request is included in v1.12.0. See Release v1.12.0 for release notes.

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.

1 participant