Skip to content

feat: improve react sync hook - #13

Merged
quolpr merged 3 commits into
mainfrom
quolpr/improve-sync-hook
Jul 3, 2026
Merged

feat: improve react sync hook#13
quolpr merged 3 commits into
mainfrom
quolpr/improve-sync-hook

Conversation

@quolpr

@quolpr quolpr commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • Bug Fixes
    • Improved async selector behavior so loading states appear correctly while data is being prepared.
    • Fixed cases where cached values could appear too early or be applied out of order during rapid updates.
    • Ensured selector results update reliably after pending preloads resolve, including across changing inputs.

@codesandbox

codesandbox Bot commented Jul 3, 2026

Copy link
Copy Markdown

Review or Edit in CodeSandbox

Open the branch in Web EditorVS CodeInsiders

Open Preview

@netlify

netlify Bot commented Jul 3, 2026

Copy link
Copy Markdown

Deploy Preview for hyperdb canceled.

Name Link
🔨 Latest commit db2bac2
🔍 Latest deploy log https://app.netlify.com/projects/hyperdb/deploys/6a47e14a43819d000817141c

@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@quolpr, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 33 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 71c35ccf-7e11-4847-aed9-64dce93e374c

📥 Commits

Reviewing files that changed from the base of the PR and between 23c3110 and db2bac2.

📒 Files selected for processing (3)
  • AGENTS.md
  • packages/hyperdb/src/react/hooks.test.ts
  • packages/hyperdb/src/react/hooks.ts
📝 Walkthrough

Walkthrough

Reworks the useAsyncSelector hook to replace the sync snapshot store with a new AsyncSelectorValueSnapshotStore abstraction, changing how initial runs, cached values, and error states are computed and published. Updates corresponding tests to assert new HybridDB caching and render-time behavior.

Changes

Async selector snapshot store rework

Layer / File(s) Summary
Value snapshot store primitives
packages/hyperdb/src/react/hooks.ts
Adds AsyncSelectorValueSnapshot, AsyncSelectorInitialRun, AsyncSelectorValueSnapshotStore types and createAsyncSelectorValueSnapshotStore factory, updates createVisibleAsyncSelectorState signature, removes unused SubscribableDB import.
Hook wiring to new store
packages/hyperdb/src/react/hooks.ts
Wires hybridCacheDB and valueSnapshotStore into useAsyncSelector initialization, useSyncExternalStore, refs, and effect dependencies.
runOnce lifecycle updates
packages/hyperdb/src/react/hooks.ts
Reworks runOnce to consume takeInitialRun(), publish resolved values, branch on initial run status, and expands rerun effect dependencies.
Render/pending behavior tests
packages/hyperdb/src/react/hooks.test.ts
Removes mocked selector store helper; asserts pending/loading state during render and correct dispatched commands without cache snapshot reads.
Cache timing and args-change tests
packages/hyperdb/src/react/hooks.test.ts
Updates assertions for delayed cache application, pending preload resolution, and args-change cleanup transitions.
Cross-args caching and sync-apply tests
packages/hyperdb/src/react/hooks.test.ts
Updates cross-args cache assertions and adds direct result assertions for synchronous selector execution.

Estimated code review effort: 4 (Complex) | ~50 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Component
  participant useAsyncSelector
  participant valueSnapshotStore
  participant hybridCacheDB

  Component->>useAsyncSelector: render
  useAsyncSelector->>valueSnapshotStore: takeInitialRun()
  valueSnapshotStore-->>useAsyncSelector: sync/async/error status
  alt initial run is async
    useAsyncSelector-->>Component: pending/loading state
    useAsyncSelector->>hybridCacheDB: runCachedSelectorMaybeAsync
    hybridCacheDB-->>useAsyncSelector: resolved value
    useAsyncSelector->>valueSnapshotStore: publish(value)
    useAsyncSelector-->>Component: success state with value
  else initial run is sync
    useAsyncSelector-->>Component: success state immediately
  else initial run is error
    useAsyncSelector->>valueSnapshotStore: getSnapshot()
    useAsyncSelector-->>Component: error state
  end
Loading

Possibly related PRs

  • will-be-done/hyperdb#6: Modifies the same useAsyncSelector implementation and hooks.test.ts expectations around the hook's internal snapshot/store behavior.
🚥 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 is broadly aligned with the React hook refactor, though it understates the async selector and cache behavior changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch quolpr/improve-sync-hook

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/hyperdb/src/react/hooks.test.ts (1)

279-555: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Update the docs for the changed useAsyncSelector behavior. The hook now skips the synchronous cache snapshot path and stays pending until the cached/async result resolves, so packages/hyperdb-doc and the root README.md should be updated to match.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/hyperdb/src/react/hooks.test.ts` around lines 279 - 555, The changed
useAsyncSelector behavior now bypasses the synchronous cache snapshot path and
remains pending until the cached or async result resolves, so update the
documentation to reflect that flow. In the docs for useAsyncSelector, plus the
root README.md and packages/hyperdb-doc, revise any descriptions that imply an
immediate synchronous cache snapshot or sync success path; reference the hook
name useAsyncSelector and the HybridDB cache behavior so the docs match the new
pending-until-resolved semantics.

Source: Coding guidelines

🧹 Nitpick comments (1)
packages/hyperdb/src/react/hooks.test.ts (1)

437-479: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Consider asserting the middle call's args too.

Only calls[0] and calls[2] are checked against project-1; the intermediate calls[1] (presumably project-2, given the "across selector args" test intent) isn't asserted, leaving a gap in verifying the args-crossing behavior end-to-end.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/hyperdb/src/react/hooks.test.ts` around lines 437 - 479, The test
for useAsyncSelector does not fully verify the selector-args transition because
it only checks the first and third runCachedSelectorMaybeAsync calls. Update
this test to also assert the middle call’s args for the project-2 invocation,
using the existing mocks.runCachedSelectorMaybeAsync.mock.calls checks, so the
across-args behavior is verified end-to-end.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/hyperdb/src/react/hooks.ts`:
- Around line 495-500: The async initial selector path in the hooks logic can
still surface an unhandled rejection if the render is abandoned before the
effect attaches handlers. Update the code in the
`runInitial`/`isPromiseLike(value)` branch so the stored promise includes an
early no-op rejection handler (for example by chaining a catch that swallows the
rejection) before returning the `{ status: "async", promise, cmds }` result.
Keep the existing `status: "sync"` and `status: "error"` behavior unchanged.
- Line 589: The reset effect in hooks.ts is depending on input.selector, which
can change on every render when the selector is created inline and cause
repeated state resets. Update the effect around the setQueryState logic to
depend only on argsKey, and use genRef.current to read the latest selector
inside the effect instead of capturing input.selector from the dependency list.

---

Outside diff comments:
In `@packages/hyperdb/src/react/hooks.test.ts`:
- Around line 279-555: The changed useAsyncSelector behavior now bypasses the
synchronous cache snapshot path and remains pending until the cached or async
result resolves, so update the documentation to reflect that flow. In the docs
for useAsyncSelector, plus the root README.md and packages/hyperdb-doc, revise
any descriptions that imply an immediate synchronous cache snapshot or sync
success path; reference the hook name useAsyncSelector and the HybridDB cache
behavior so the docs match the new pending-until-resolved semantics.

---

Nitpick comments:
In `@packages/hyperdb/src/react/hooks.test.ts`:
- Around line 437-479: The test for useAsyncSelector does not fully verify the
selector-args transition because it only checks the first and third
runCachedSelectorMaybeAsync calls. Update this test to also assert the middle
call’s args for the project-2 invocation, using the existing
mocks.runCachedSelectorMaybeAsync.mock.calls checks, so the across-args behavior
is verified end-to-end.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b29e1911-8885-49ce-bdc3-3b1c8420bbaa

📥 Commits

Reviewing files that changed from the base of the PR and between 35ec16e and 23c3110.

📒 Files selected for processing (2)
  • packages/hyperdb/src/react/hooks.test.ts
  • packages/hyperdb/src/react/hooks.ts

Comment thread packages/hyperdb/src/react/hooks.ts Outdated
Comment thread packages/hyperdb/src/react/hooks.ts
@quolpr
quolpr merged commit 4b3354e into main Jul 3, 2026
7 of 8 checks passed
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