Skip to content

migrate lazy queries to Apollo Client 4#2916

Merged
huumn merged 47 commits intostackernews:masterfrom
Soxasora:refactor/lazy-queries-ac4-migration
Apr 27, 2026
Merged

migrate lazy queries to Apollo Client 4#2916
huumn merged 47 commits intostackernews:masterfrom
Soxasora:refactor/lazy-queries-ac4-migration

Conversation

@Soxasora
Copy link
Copy Markdown
Member

@Soxasora Soxasora commented Apr 14, 2026

Description

Based on #2904

useLazyQuerys used outside of user interaction have the potential to throw AbortErrors much more frequently than before:

  • The component unmounts while the query is in flight
  • A new query is started by calling the execute function while a previous query is in flight
    ac4 migration

We have some anti-patterns going on, some places should have useQuery and other places should use client.query

  1. useLazyQuery + useEffect: the execute is only ran by useEffect and never reaches the user, can use useQuery with skip
    • BaseSuggest components/form.js
    • PostEdit pages/items/[id]/edit.js
  2. only execute: doesn't use any of the following: data, loading, error and can use client.query
    • SubMultiSelect components/sub-select.js
    • TerritoryForm components/territory-form.js
    • useCrossposter components/use-crossposter.js
    • useLexicalUploadFees components/editor/plugins/upload.js
    • useSuggestions components/editor/plugins/mentions.js
    • components/payIn/hooks/use-auto-retry-pay-ins.js

While instead sub-popover.js, item-popover.js, user-popover.js, link-form.js, wallets/.../logger.js all use useLazyQuery correctly.

Additional Context

components/payIn/hooks/use-auto-retry-pay-ins.js polls correctly every 30 seconds, but I didn't do deep QA.

Checklist

Are your changes backward compatible? Please answer below:

Yes

On a scale of 1-10 how well and how have you QA'd this change and any features it might affect? Please answer below:

6, everything works smoothly, couldn't give it a 7 just because of missing QA on components/payIn/hooks/use-auto-retry-pay-ins.js

Did you use AI for this? If so, how much did it assist you?
Plan


Note

Medium Risk
Changes several async data-fetch paths (editor mention suggestions, territory lookups, post edit fee line items, and pay-in retry polling) to avoid Apollo Client 4 AbortError behavior; risk is moderate due to altered fetch timing/caching and error handling in user-facing and payment-related flows.

Overview
Migrates multiple non-interactive useLazyQuery usages to either useApolloClient().query (one-off fetches) or useQuery with skip (effect-driven fetches) to reduce Apollo Client 4 in-flight cancellation/AbortError issues.

This updates mention/autocomplete suggestion fetching, territory info lookups, crossposter item loading, and failed pay-in polling to use direct client.query with explicit fetch policies, and refactors pages/items/[id]/edit.js to derive territory-add fee line items from a SUBS useQuery result instead of an effect + lazy query.

Reviewed by Cursor Bugbot for commit f4fae62. Bugbot is set up for automated code reviews on this repo. Configure here.

Soxasora and others added 23 commits April 5, 2026 16:28
…upgrade Apollo Client/Server, other libs that didn't support React 19

- Next.js 14.2.25 -> 15.5.14
- React 18.3.1 -> 19.2.4
- GraphQL 16.9.0 -> 16.13.2
- Apollo Client 3.11.8 -> 4.1.6
- Apollo Server 4.11.0 -> 5.5.0
- Apollo Server Integrations for Nextjs 3.1.0 -> 4.1.0
- \@yudiel/react-qr-scanner 2.0.8 -> 2.5.1
- qrcode.react 4.0.1 -> 4.2.0
- react-avatar-editor 13.0.2 -> 15.1.0
- recharts 2.13.0 -> 2.15.4
  - react-is 19.2.4 override
  - can be removed after upgrade to recharts 3.x
- eslint-plugin-next 14.2.15 -> 15.5.14
+ eslint-config-next 15.5.14
… a server external

DefinePlugin can't otherwise replace the env var internally used by next-plausible to determine if we're using the proxy or not
…get the full error where errors are manually handled
…LOWED_DEV_ORIGINS env var for additional allowed origins
…inal Apollo Client 3 behavior (don't re-render components unless data changes)
- `index` state for navigation
- `useQuery` skips when query is undefined
- memoized suggestions
@Soxasora Soxasora changed the title migrate lazy queries to ac4 migrate lazy queries to Apollo Client 4 Apr 14, 2026
@Soxasora Soxasora marked this pull request as ready for review April 15, 2026 11:36
Comment thread components/territory-form.js Outdated
Comment thread components/form.js Outdated
Comment thread components/form.js Outdated
Comment thread components/editor/plugins/upload.js Outdated
Comment thread components/form.js Outdated
Comment thread pages/items/[id]/edit.js
Comment thread components/form.js Outdated
Copy link
Copy Markdown
Member

@huumn huumn left a comment

Choose a reason for hiding this comment

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

The main I issue I found with this was a regression in race conditions where successive queries can be executed and we need the last query rather than the last response (and we aren't debouncing otherwise). I'm not sure what the right move is, but we might want to establish some kind of abort/ignore pattern for these, debounce them (lowering the probability of races), or continue with useLazyQuery (which has the annoying abort pattern baked in).

  • territory-form.js when checking for an archived territory
    • e.g. bitcoin is archived, I type out bitcoin then bitcoin1, bitcoin1 returns available but then the bitcoin response comes later and bitcoin1 is marked as archived
  • components/editor/plugins/upload.js has a similar race

The other issue I found matched cursorbot's findings: suggestions and suggestions index can go out of sync now.


this is all bot review. by my eye it looks good - I would've missed the query races.

@Soxasora
Copy link
Copy Markdown
Member Author

Soxasora commented Apr 27, 2026

I couldn't reproduce without an artificial delay but this needs to be fixed anyway. We can probably keep useLazyQuery for some things, its abort mechanism is actually useful here.

I'll check where we need to switch back!

edit:

  • territory-form and upload now use useLazyQuery again, it makes more sense to switch back and benefit from the abort mechanism.
  • I was evaluating a switch back for BaseSuggest's mentions, but since we can benefit from cache access with useQuery it made sense to just fix the desync issue with an activeIndex computed on the current suggestions array state.

It seems like everything else is textbook correct.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 8676013. Configure here.

Comment thread components/payIn/hooks/use-auto-retry-pay-ins.js
Comment thread components/form.js Outdated
@Soxasora Soxasora requested a review from huumn April 27, 2026 19:29
@huumn huumn merged commit 7a75942 into stackernews:master Apr 27, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants