Skip to content

prevent duplicate autocomplete initialization on first interaction - #732

Open
Montana wants to merge 2 commits into
StackExchange:masterfrom
Montana:fix-autocomplete-and-ci
Open

prevent duplicate autocomplete initialization on first interaction#732
Montana wants to merge 2 commits into
StackExchange:masterfrom
Montana:fix-autocomplete-and-ci

Conversation

@Montana

@Montana Montana commented Jul 1, 2026

Copy link
Copy Markdown

Hi StackExchange,

Two independent fixes:

  1. fix: the autocomplete initializes twice on the first click, creating two Autocomplete instances bound to the same input.
  2. ci: the GitHub Actions workflows pin deprecated action versions running on the Node 16 runtime.

Both are small and self-contained; they're split into separate commits.

1. Duplicate autocomplete initialization

Problem

The autocomplete is lazy-loaded on first interaction, with two { once: true } listeners:

  • a click listener on .js-autocomplete-container
  • a focus listener on the input inside it

A single mouse click on the input fires both: focus fires on mousedown, then the click bubbles up to the container. Both call initializeAutocomplete().

The existing guard was meant to dedupe:

if (document.querySelector(".js-autocomplete-input")?.getAttribute("type") === "search") {
    return; // already initialized
}

But type="search" is only set by Algolia after the dynamic import() of the autocomplete module resolves, which is asynchronous. So when both listeners fire in the same gesture, both calls pass the guard before either finishes importing, and two instances get constructed on the same input (duplicate event listeners, double submits). Keyboard/tab users avoid it (focus only, no click); mouse users hit it on the first click.

Fix

Replace the async DOM-attribute check with a synchronous boolean set before the first await, so a re-entrant call returns immediately:

let autocompleteInitialized = false;

async function initializeAutocomplete(): Promise<void> {
    if (autocompleteInitialized) {
        return;
    }
    autocompleteInitialized = true;

    const Autocomplete = await loadAutocompleteAsync();
    // ...
}

2. Deprecated GitHub Actions

Problem

.github/workflows/main.yml pins actions/checkout@v3 and actions/setup-node@v3, both of which run on the Node 16 runtime that GitHub has deprecated. They emit deprecation warnings in CI today and are on a removal path. The two dependabot workflows pin dependabot/fetch-metadata@v1, likewise superseded by v2.

Fix

  • actions/checkout@v3 -> @v4
  • actions/setup-node@v3 -> @v4, plus cache: npm (the repo has a lockfile and uses npm ci, so this is a free CI speedup)
  • dependabot/fetch-metadata@v1 -> @v2 in both auto-upgrade-caniuse-lite.yml and dependabot-auto-merge.yml

The fetch-metadata v2 bump is drop-in (same outputs).

Testing

  • npm ci && npm run build passes locally.
  • The autocomplete fix was verified against the interaction that triggers it (clicking the input rather than tabbing to it).

Notes / out of scope

While reviewing I also noticed helpers/static-data.ts types imageUrl as string but logoMapping only covers seven browsers, so any browser not in the map would render <img src="">. I confirmed this does not currently trigger: the @stackoverflow/browserslist-config query explicitly excludes every unmapped browser, so the resolved set is exactly the seven that are mapped. Left it alone to keep this PR focused; happy to add a guard in a follow-up if you'd prefer the hardening.

Montana added 2 commits July 1, 2026 09:37
Clicking the input fires both the container click listener and the input
focus listener in the same gesture. The previous guard checked a DOM
attribute that Algolia only sets after the dynamic import resolves, so both
calls passed the guard and created two Autocomplete instances bound to the
same input. Replace it with a synchronous boolean set before the first await.
actions/checkout@v3 and actions/setup-node@v3 run on the deprecated Node 16
runtime and emit warnings; bump both to v4. Also bump dependabot/fetch-metadata
to v2 and enable npm caching in setup-node to speed up CI.
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