Skip to content

fix: Hold React dispatch until the store commits - #4098

Closed
ntucker wants to merge 1 commit into
masterfrom
cursor/hold-precommit-dispatch-185b
Closed

ntucker wants to merge 1 commit into
masterfrom
cursor/hold-precommit-dispatch-185b

Conversation

@ntucker

@ntucker ntucker commented Sep 24, 2026

Copy link
Copy Markdown
Collaborator

Motivation

useSuspense of an endpoint that is already resolved can stay on its fallback when that response is dispatched before DataProvider has committed. React restarts the provider, the update is dropped, and a fresh NetworkManager refetches in a loop. A slow endpoint misses this because its response arrives after commit.

Solution

Until the store's first commit, usePromisifiedDispatch records reducer actions and returns the same commit promise it returns today. It does not call React's dispatch. A layout effect flushes that queue in order. The passive effect does not resolve the promise on the mount snapshot, so listeners see the reducer state after the flush commits. After that first effect, dispatches go straight to React.

Fetching still starts during render. NetworkManager.idleCallback is unchanged. This does not re-resolve a fetch that was delivered to a provider React discarded. A managers array kept outside DataProvider can still leave Suspense on the fallback in that case.

Open questions

N/A

Open in Web Open in Cursor 

Queue reducer actions that arrive before the first commit and flush them after the provider mounts, so useSuspense of an already-resolved endpoint can retry when React restarts DataProvider.

Co-authored-by: Nathaniel Tucker <me@ntucker.me>
@changeset-bot

changeset-bot Bot commented Sep 24, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 88e1542

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 17 packages
Name Type
@data-client/core Patch
@data-client/endpoint Patch
@data-client/graphql Patch
@data-client/img Patch
@data-client/normalizr Patch
@data-client/react Patch
@data-client/rest Patch
@data-client/test Patch
@data-client/use-enhanced-reducer Patch
@data-client/vue Patch
example-benchmark Patch
example-benchmark-react Patch
normalizr-github-example Patch
normalizr-redux-example Patch
normalizr-relationships Patch
test-bundlesize Patch
coinbase-lite Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Sep 24, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
docs-site Ignored Ignored Sep 24, 2026 4:39pm UTC

Request Review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Benchmark React

Details
Benchmark suite Current: 88e1542 Previous: a76996a Ratio
data-client: getlist-100 135.14 ops/s (± 4.6%) 125 ops/s (± 4.8%) 0.92
data-client: getlist-500 43.86 ops/s (± 3.4%) 39.84 ops/s (± 5.5%) 0.91
data-client: update-entity 333.33 ops/s (± 9.4%) 312.5 ops/s (± 7.2%) 0.94
data-client: update-user 303.03 ops/s (± 7.6%) 294.12 ops/s (± 7.8%) 0.97
data-client: getlist-500-sorted 42.93 ops/s (± 9.7%) 43.39 ops/s (± 9.2%) 1.01
data-client: update-entity-sorted 294.12 ops/s (± 5.8%) 263.16 ops/s (± 5.9%) 0.89
data-client: update-entity-multi-view 322.58 ops/s (± 8.1%) 277.78 ops/s (± 7.0%) 0.86
data-client: list-detail-switch-10 10.41 ops/s (± 10.6%) 7.22 ops/s (± 5.2%) 0.69
data-client: update-user-10000 67.57 ops/s (± 15.3%) 71.43 ops/s (± 12.4%) 1.06
data-client: invalidate-and-resolve 36.77 ops/s (± 5.9%) 32.95 ops/s (± 5.6%) 0.90
data-client: unshift-item 200 ops/s (± 4.6%) 188.68 ops/s (± 5.9%) 0.94
data-client: delete-item 270.27 ops/s (± 6.2%) 250 ops/s (± 4.4%) 0.93
data-client: move-item 161.33 ops/s (± 9.9%) 158.77 ops/s (± 8.3%) 0.98

This comment was automatically generated by workflow using github-action-benchmark.

@github-actions

Copy link
Copy Markdown
Contributor

Size Change: +217 B (+0.21%)

Total Size: 103 kB

📦 View Changed
Filename Size Change
examples/test-bundlesize/dist/rdcClient.js 11 kB +108 B (+1%)
examples/test-bundlesize/dist/rdcNextjs.js 12.4 kB +109 B (+0.88%)
ℹ️ View Unchanged
Filename Size
examples/test-bundlesize/dist/App.js 1.46 kB
examples/test-bundlesize/dist/polyfill.js 307 B
examples/test-bundlesize/dist/rdcEndpoint.js 8.07 kB
examples/test-bundlesize/dist/rdcPipeableStream.js 9.63 kB
examples/test-bundlesize/dist/react.js 59.6 kB
examples/test-bundlesize/dist/webpack-runtime.js 784 B

compressed-size-action

@ntucker ntucker closed this Sep 24, 2026
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.

2 participants