Skip to content

feat: sync route params with compare form inputs#119

Merged
O2sa merged 2 commits intoO2sa:mainfrom
mvanhorn:osc/21-sync-url-params
Apr 26, 2026
Merged

feat: sync route params with compare form inputs#119
O2sa merged 2 commits intoO2sa:mainfrom
mvanhorn:osc/21-sync-url-params

Conversation

@mvanhorn
Copy link
Copy Markdown
Contributor

Summary

Closes #21. The home page now treats ?username=u1&username=u2 as the source of truth for the compare form and results:

  • Mount with URL params populates the inputs and auto-loads the comparison.
  • Submitting the form pushes the URL via router.push so the result is shareable / copy-pasteable.
  • Back/forward buttons resync the form and re-fetch as needed.
  • swap and reset push their corresponding URL state too.

Why this matters

The form was previously seeded with hardcoded pbiggar / CoralineAda defaults and the URL never reflected what was being compared, so a user couldn't share or bookmark a result. The issue's two main tasks (update the url params when the form values change + when the page initialize check the url params to update the form values and fetching the required data) both land here.

The implementation lifts username state out of CompareForm into app/page.tsx so the URL can drive both. The form becomes controlled — it accepts username1 / username2 / setUsername1 / setUsername2 props from the page and no longer owns local input state.

A useEffect watching searchParams calls into a useEffectEvent-wrapped syncToUrl helper. syncToUrl is the single resync entry point used for initial mount AND back/forward navigation; it short-circuits via lastFetchedPairRef so our own router.push calls don't trigger duplicate fetches.

Changes

  • app/page.tsx:
    • Wrapped the body in <Suspense> (required by useSearchParams) and split the body into a HomePageInner component.
    • Added useRouter + useSearchParams to read the URL.
    • Lifted username1 / username2 state from the form into the page; seeded from URL params.
    • handleCompare now router.pushes the URL before fetching, and stamps lastFetchedPairRef.
    • swapUsers and reset push the corresponding URL state.
    • New searchParams-watching useEffect + useEffectEvent resyncs form/results on URL change.
  • components/compare-form.tsx:
    • Accepts username1 / username2 / setUsername1 / setUsername2 props.
    • Removed local useState and the hardcoded pbiggar / CoralineAda defaults.
    • handleSwap / handleReset keep their existing parent-callback shape.

Testing

  • pnpm run buildCompiled successfully and Finished TypeScript both pass on this diff. The build then fails at Collecting page data with Missing GITHUB_TOKEN, but that's a pre-existing failure of the /api/compare route in any local build without a token, not anything this PR introduced.
  • pnpm run lint — same 5 pre-existing issues (3 errors / 2 warnings) reported on master. None in app/page.tsx or components/compare-form.tsx.

Manual verification flow:

  1. Visit / — empty form, empty state.
  2. Compare two users — inputs filled, URL becomes /?username=u1&username=u2, results load.
  3. Copy that URL into a new tab — same comparison auto-loads.
  4. Change usernames + submit again — URL updates, results update.
  5. Hit Back — URL reverts and the form/results follow it.

This contribution was developed with AI assistance (Codex).

Round-2 review: the previous version only consumed search params on
initial mount, so router.push from compare/swap/reset put history
entries that the back button couldn't restore. Now a useEffect watches
searchParams and resyncs username1/username2 + triggers a re-fetch when
the URL pair differs from the last fetched pair. lastFetchedPairRef
short-circuits the loop with our own router.push.
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 26, 2026

@mvanhorn is attempting to deploy a commit to the osama's projects Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions
Copy link
Copy Markdown

Thank you for the pull request! ✅

A maintainer will review this soon. Please be patient while we take a look. 🙌

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 26, 2026

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

Project Deployment Actions Updated (UTC)
dev-impact Ready Ready Preview, Comment Apr 26, 2026 8:42pm

Comment thread app/page.tsx

<div className="w-full flex-1 max-w-6xl mx-auto px-4 py-10 space-y-6">
<CompareForm
username1={username1}
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

It looks like some new props were added to the CompareForm call, but the component itself wasn't updated to receive them. This is breaking the build right now.

Could you sync the component definition and double-check that it loads okay in live mode?

The PR call site lifted username1/username2 and their setters into
HomePageInner so URL searchParams could drive the form, but the
component itself still owned its own useState pair. That broke the
build and meant the prop-passed values were ignored at runtime.

Move the four values into CompareFormProps, drop the internal
useState, and let parent-supplied swapUsers/reset handle clearing
and swapping. The local placeholder defaults ("pbiggar",
"CoralineAda") are gone; the parent now seeds initial state from
searchParams.
@mvanhorn
Copy link
Copy Markdown
Contributor Author

Fixed in 68fa4d3. CompareFormProps now declares username1, username2, setUsername1, setUsername2, and the internal useState pair is gone, so the parent's URL-synced state is the single source. handleSwap and handleReset just delegate to swapUsers/reset.

Verified locally: pnpm run build succeeds (TypeScript clean, 4 of 4 pages generated). The remaining Vercel failure on the previous push was the type mismatch you flagged.

@O2sa O2sa merged commit a778196 into O2sa:main Apr 26, 2026
2 checks passed
@github-actions
Copy link
Copy Markdown

Thank you, @mvanhorn! Another great contribution merged! 🚀

You've been a fantastic contributor! We truly appreciate your continued support.

@mvanhorn
Copy link
Copy Markdown
Contributor Author

Appreciate the merge @O2sa. Hope the URL-shareable compare flow turns out useful for #21.

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.

Sync the route parameters with the form inputs

2 participants