Skip to content

fix: respect preventDefault from user click handlers - #627

Merged
redonkulus merged 1 commit into
masterfrom
claude/open-issues-validation-ec4095
Oct 20, 2026
Merged

redonkulus merged 1 commit into
masterfrom
claude/open-issues-validation-ec4095

Conversation

@redonkulus

Copy link
Copy Markdown
Collaborator

Fixes #568, fixes #569.

Problem

The i13n click listener is a native listener on the element, so it runs before React's onClick handlers (delegated to the root). For links and submit buttons it called e.preventDefault() itself, then navigated or submitted in code (location.assign / form.submit()) after the beacon. A later preventDefault() from user code had no effect.

Since #391 (switch to currentTarget), this means:

Fix (src/libs/clickHandler.js)

  • Record whether any handler cancelled the click, before (e.defaultPrevented) or after the i13n listener (by wrapping e.preventDefault on the event). Skip the redirect/submit if so. The click beacon still fires.
  • Defer the redirect with setTimeout(…, 0). With no plugin handling the event, the beacon callback runs synchronously, before React's handlers.
  • Submit with form.requestSubmit(submitter) when available, so onSubmit handlers and constraint validation run. form.submit() skips both. Falls back to form.submit().

Behavior change to note

Redirects and submits now happen one macrotask later than before. In practice this is invisible, since they already waited for the beacon when plugins were registered.

Tests

  • src/libs/tests/clickHandler.test.js: unit tests for prevented-before, prevented-after (link and form), and requestSubmit. The two _top/_parent tests now wait for the deferred redirect.
  • src/components/tests/preventDefault.test.jsx: end-to-end tests that reproduce both issue scenarios with real I13nButton / I13nAnchor and React handlers, plus the unprevented happy paths.

All 6 new tests fail on master and pass with this change. Full suite: 60 passed, 1 skipped. npm run lint is clean.

🤖 Generated with Claude Code

The i13n click listener cancels the native default action and redirects
programmatically after the beacon, so a preventDefault() from a React
onClick (which runs later, at the root) had no effect. Since #391 this
caused I13nButton to submit its form (#569) and I13nAnchor to navigate
even when an inner element's handler called preventDefault (#568).

- Track preventDefault calls made before or after the i13n listener and
  skip the redirect/submit if any handler cancelled the click.
- Defer the redirect until the click dispatch finishes, since the beacon
  callback can run synchronously when no plugin handles the event.
- Submit forms with requestSubmit(submitter) when available so submit
  handlers and constraint validation run; fall back to form.submit().

Fixes #568
Fixes #569

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@redonkulus
redonkulus merged commit 6eb79ea into master Oct 20, 2026
2 checks passed
@redonkulus
redonkulus deleted the claude/open-issues-validation-ec4095 branch October 20, 2026 20:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant