Skip to content

fix: react input issues#61

Merged
nathanfallet merged 2 commits intomainfrom
fix/react-input-issues
Mar 1, 2026
Merged

fix: react input issues#61
nathanfallet merged 2 commits intomainfrom
fix/react-input-issues

Conversation

@nathanfallet
Copy link
Member

@nathanfallet nathanfallet commented Mar 1, 2026

Problem

When automating React controlled inputs, clearInput() and clearInputByDeleting() silently fail to notify React, leaving the component state stale. The real-world consequence is a mixed value when re-filling a pre-filled input — e.g. old value "10", new value "25", actual result "025" or "1025".

Root cause

React installs an instance-level value property setter on controlled inputs (its _valueTracker mechanism). Direct el.value = x assignments in JavaScript go through this setter, updating both the DOM value and the tracker's "last known value" simultaneously. When an input event then fires, React compares el.value === tracker.getValue() — they match — so React concludes nothing changed and never calls onChange. The clear appears to work at the DOM level but React silently reverts it on the next render cycle.

Both methods were affected:

  • clearInput() used element.value = "" with no event dispatch at all — a double failure
  • clearInputByDeleting() used el.value = el.value.slice(1) on each iteration, which also went through the tracker setter and then fired an input event that React ignored

Fix

  • clearInput() — replaced the direct .value assignment with a call to the native prototype setter (Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value').set.call(el, '')), which bypasses the tracker entirely. Added an InputEvent dispatch so React detects the mismatch and fires onChange.

  • clearInputByDeleting() — removed the JS value mutation (el.value = el.value.slice(1)) and the manual event dispatch entirely. The CDP dispatchKeyEvent with key="Delete" at cursor position 0 already uses the browser's native text-editing pipeline, which bypasses the tracker and correctly triggers React's change detection. The JS snippet now only reads el.value.length to check the remaining character count.

Tests

Added ReactControlledInputTest with an accompanying HTML fixture that faithfully reproduces the _valueTracker mechanism in vanilla JS — same instance-level setter, same mismatch comparison, same state tracking.

Test What it proves
testClearInputDoesNotNotifyReact Before fix: clearInput() leaves React state at "10" instead of ""
testClearInputByDeletingDoesNotNotifyReact Before fix: clearInputByDeleting() leaves React state at "0" instead of ""
testFillReactControlledInputProducesMixedValue Before fix: clear + re-render + insert produces "025" instead of "25"

All three tests failed before the fix and pass after. The existing ElementTest.testInput (plain HTML input) continues to pass, confirming no regression for non-React inputs.

@codecov
Copy link

codecov bot commented Mar 1, 2026

Codecov Report

❌ Patch coverage is 66.66667% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...Main/kotlin/dev/kdriver/core/dom/DefaultElement.kt 66.66% 0 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

@nathanfallet nathanfallet merged commit 81ab04c into main Mar 1, 2026
5 of 8 checks passed
@nathanfallet nathanfallet deleted the fix/react-input-issues branch March 1, 2026 13:23
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