question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Bug: Form reset lost checkbox onChange event

See original GitHub issue

Hi, I use checkbox uncontrolled mode, onChange in form reset after, lose onChange.

<input type="checkbox" onChange={onChange} />

but use add ref.addEventListener(‘change’, onChange) is ok

const checkRef = useRef<HTMLInputElement>();
useEffect(() => {
        if (checkboxRef) {
            checkboxRef.current.addEventListener('change', onChange);
        }
    }, []);

<input type="checkbox" ref="checkboxRef" onChange={onChange} />

React version: 16.13 and old

Steps To Reproduce

  1. checkbox => checked
  2. form reset
  3. checked => checked

Link to code example: not react is ok reset is lose target onChange

The current behavior

  1. checkbox => checked (target onChange)
  2. form reset
  3. checked => checked (lose target onChange)

The expected behavior

  1. checkbox => checked (target onChange)
  2. form reset
  3. checked => checked (target onChange)

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:6
  • Comments:8

github_iconTop GitHub Comments

1reaction
bvaughncommented, Jun 25, 2020

I’m probably not the right person to review event stuff. Can you make the changes to the source files, then submit a PR?

0reactions
kassiomaiacommented, Jun 25, 2020

Did some research:

I used even simpler code:

function onChange() {
  console.log('onChange');
}

function App() {
  return (
        <form>
          <input type="checkbox" onChange={onChange} />
          <button type="reset">Reset</button>
        </form>
  );
}
  • It only happens when then checkbox is checked when you reset the form then check it again.
  • It does NOT happen when the checkbox is unchecked when you reset the form then check it.

In the first case it happens when checking the second time because in updateValueIfChanged lastValue and nextValue are both true. So the function returns false and the onChange will be skipped.

The tracker on the node did not record the reset. I see that a reset event is fired for the target form but nothing seems to happen with that event. I do not see any code in react-dom that collect all inputs of a form to do something, so I am a bit reluctant to start adding something that big.

I would be interested in trying to make a fix for this.

I wrote a pice of code but I’m not sure if it’s on the right place, did this directly on react-dom.development.js.

@bvaughn, Is dispatchEvent the right place for this kind of actions?

function attemptToResetTrackers(nativeEvent) {
  var target = nativeEvent.target

  if (target && target.tagName === 'FORM') {
    for (var i = 0; i <= nativeEvent.target.length; i++) {
      var node = nativeEvent.target[i]

      if (node) {
        var tracker = getTracker(node)

        if (tracker) {
          tracker.setValue(node.defaultValue)
        }
      }

    }
  }
}
function dispatchEvent(topLevelType, eventSystemFlags, container, nativeEvent) {
  if (!_enabled) {
    return;
  }

  // Reset trackers when reset is called
  if (topLevelType === 'reset') {
    attemptToResetTrackers(nativeEvent)
  }

  if (hasQueuedDiscreteEvents() && isReplayableDiscreteEvent(topLevelType)) {
    // If we already have a queue of discrete events, and this is another discrete
    // event, then we can't dispatch it regardless of its target, since they
    // need to dispatch in order.
    queueDiscreteEvent(null, // Flags that we're not actually blocked on anything as far as we know.
    topLevelType, eventSystemFlags, container, nativeEvent);
    return;
  }

  var blockedOn = attemptToDispatchEvent(topLevelType, eventSystemFlags, container, nativeEvent);

  if (blockedOn === null) {
    // We successfully dispatched this event.
    clearIfContinuousEvent(topLevelType, nativeEvent);
    return;
  }

  if (isReplayableDiscreteEvent(topLevelType)) {
    // This this to be replayed later once the target is available.
    queueDiscreteEvent(blockedOn, topLevelType, eventSystemFlags, container, nativeEvent);
    return;
  }

  if (queueIfContinuousEvent(blockedOn, topLevelType, eventSystemFlags, container, nativeEvent)) {
    return;
  } // We need to clear only if we didn't queue because
  // queueing is accummulative.


  clearIfContinuousEvent(topLevelType, nativeEvent); // This is not replayable so we'll invoke it but without a target,
  // in case the event system needs to trace it.

  {
    dispatchEventForLegacyPluginEventSystem(topLevelType, eventSystemFlags, nativeEvent, null);
  }
} // Attempt dispatching an event. Returns a SuspenseInstance or Container if it's blocked.
Read more comments on GitHub >

github_iconTop Results From Across the Web

148118 – Form-reset triggers superfluous onchange event in ...
KDE Bugtracking System – Bug 148118 Form-reset triggers superfluous onchange event in radiobutton and checkbox Last modified: 2008-10-18 18:39:23 UTC.
Read more >
Checkbox onchange event not firing - Stack Overflow
Problem is, when I click on it, the onchange is fired alright, but when I use the first to change it's state, the...
Read more >
Event Checkbox onChange missing - Bug - AppGyver forums
Hi @user6, you can create a true/false page variable that you bind to the checkbox value, and then listen to “Page variable changed”...
Read more >
Forms in HTML documents - W3C
A control's initial value does not change. Thus, when a form is reset, each control's current value is reset to its initial value....
Read more >
Form - Ant Design
Select a option and change input text above. Submit Reset Fill form. Form methods (Class component). We recommend use Form.useForm to create data...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found