Skip to content

fix: reconcile native styles when layout effects reconnect - #690

Merged
Brentlok merged 1 commit into
uni-stack:mainfrom
eliotgevers:fix/native-style-effect-reconnection
Sep 25, 2026
Merged

Brentlok merged 1 commit into
uni-stack:mainfrom
eliotgevers:fix/native-style-effect-reconnection

Conversation

@eliotgevers

@eliotgevers eliotgevers commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Native useStyle subscribers now catch dependency updates missed while their layout effects were disconnected. Memoized content revealed by Activity or Suspense keeps its state and immediately resolves the current styles.

Fixes #689.

Reproduction: https://github.com/eliotgevers/uniwind-activity-reproduction

Why

React can recreate layout effects without rendering unchanged children. Subscribing again only handles future notifications. Compare the current dependency revision with the revision captured alongside the rendered styles, after registering the listener, and schedule a render if they differ.

The comparison uses a render-local value rather than mutating a ref during render. The effect retains the existing dependency-set key, so normal style updates do not cause unnecessary resubscription. No new API or dependency is introduced.

Verification

  • Two native regressions using the existing renderUniwind helper: Activity catches theme changes in both directions and continues receiving visible updates; Suspense catches a theme change on reveal. Stable children ensure ordinary parent renders cannot mask the bug.
  • Both tests fail on stock and pass with the fix. Full native suite: 49 suites / 180 tests pass. Test typecheck and changed-file formatting pass.
  • The unchanged implementation also passed package build, source typecheck, lint, and circular-dependency checks during the investigation. Additional local lifecycle checks and an isolated iOS simulator reproduction verified state retention, effect suspension, and hidden variable updates. These investigation helpers are not part of the patch.

Scope

This repairs the OSS JS style subscription boundary. It does not change the native Pro implementation, React's Activity behavior, or app lifecycle/background rendering. Hidden component effects remain disconnected. Static styles and scoped themes retain their existing dependency behavior.

Summary by CodeRabbit

  • Bug Fixes
    • Style updates now stay in sync with the current theme when a view becomes visible again after being hidden, or resumes after a suspended render. Theme changes made while a view is inactive are reflected when it reconnects, helping prevent stale styles from appearing on screen.

@coderabbitai

coderabbitai Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: d614fdc6-5515-49ed-bc47-10ff92b4a9d7

📥 Commits

Reviewing files that changed from the base of the PR and between c7978fd and aa2d09c.

📒 Files selected for processing (2)
  • packages/uniwind/src/components/native/useStyle.ts
  • packages/uniwind/tests/native/components/activity-reconnection.test.tsx

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


📝 Walkthrough

Walkthrough

The native useStyle hook now checks for dependency changes after its layout effect reconnects. New tests cover theme updates while a child is hidden by React.Activity or suspended by React.Suspense.

Changes

Native style reconnection

Layer / File(s) Summary
Reconcile styles after effect reconnection
packages/uniwind/src/components/native/useStyle.ts, packages/uniwind/tests/native/components/activity-reconnection.test.tsx
useStyle captures a dependency snapshot before its layout effect and checks it after subscribing. It rerenders when the snapshots differ. Tests cover theme changes during Activity hiding and Suspense.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Medium

Merge Risk: ⚪ Minimal · up to aa2d0

The native style reconnection fix is mergeable after normal checks; no actionable risk is established.

🚥 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 and concisely describes the main change: reconciling native styles when layout effects reconnect. It matches the implementation and regression tests for Activity and Suspense reconne…
Linked Issues check ✅ Passed The change satisfies issue [#689]. useStyle captures the rendered dependency snapshot, subscribes with the existing dependency set, and calls rerender() when the live revision differs after effect…
Out of Scope Changes check ✅ Passed The diff is limited to the OSS native useStyle subscription boundary and focused native regression tests. The test changes directly verify issue [#689]. No changes affect native Pro, React Activity …
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 2…
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

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 24, 2026

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

The PR appears safe to merge, with the reconnection path correctly closing the stale-style window and focused regressions covering the intended lifecycle behavior.

Summary

This PR reconciles native styles when React reconnects layout effects without rerendering their components.

  • Captures the dependency revision associated with rendered styles.
  • Subscribes before comparing against the current revision, closing the render-to-subscription update gap.
  • Adds Activity and Suspense regression coverage for hidden theme updates.
  • No actionable correctness, security, or repository-rule violations were identified.
Diagram
sequenceDiagram
    participant React
    participant Style as useStyle
    participant Listener as UniwindListener
    React->>Style: Render resolved styles
    Style->>Listener: Capture dependency snapshot
    React->>Style: Disconnect layout effect
    Listener->>Listener: Dependency revision changes
    React->>Style: Reconnect effect without render
    Style->>Listener: Subscribe
    Style->>Listener: Read current snapshot
    alt Revision changed
        Style->>React: Schedule catch-up render
        React->>Style: Resolve current styles
    end
Loading

Reviews (1) · Last reviewed commit: "fix: reconcile native styles when layout..."

@Brentlok

Copy link
Copy Markdown
Contributor

Thanks for contribution!

@Brentlok
Brentlok merged commit e8a1f0c into uni-stack:main Sep 25, 2026
3 checks passed
@eliotgevers
eliotgevers deleted the fix/native-style-effect-reconnection branch September 25, 2026 12:06
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.

OSS built-in styles stay stale after Activity or Suspense reconnects unchanged children

2 participants