最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - react checkbox: event.preventDefault() breaks onChange function - why? - Stack Overflow

programmeradmin6浏览0评论

I have just found a stray event.preventDefault() that was breaking my checkboxes' onChange handler:

import { Component } from 'react';

class App extends Component {
  constructor(props) {
    super(props)
    this.state = {
      accepted: false
    }
  }

  changeChecked = (event) => {
    this.setState((state) => ({
      accepted : !state.accepted
    }));
    event.preventDefault(); // <- this very bad
  }

  render() {
    return (
      <input
        type="checkbox" 
        onChange={this.changeChecked}
        checked={this.state.accepted}
      />
    );
  }
}

export default App;

The resulting behaviour is a correctly updated state on first click, but the checkbox only changes to its 'checked' appearance on the next rerender, eg. a second click.

Why is that? Isn't it the point of controlled ponents to work independently from browser events?

Someone explaining this to me would definitely ease the pain of hours spent boiling down my plex use case. Thank you!

Update: Here's a quick Codepen example demonstrating the odd behaviour. I included an 'unprevented checkbox' and one with a prevented onClick event as parison. Notice how the one with prevented onChange switches its appearance to its actual state as soon as I click a different checkbox.

I have just found a stray event.preventDefault() that was breaking my checkboxes' onChange handler:

import { Component } from 'react';

class App extends Component {
  constructor(props) {
    super(props)
    this.state = {
      accepted: false
    }
  }

  changeChecked = (event) => {
    this.setState((state) => ({
      accepted : !state.accepted
    }));
    event.preventDefault(); // <- this very bad
  }

  render() {
    return (
      <input
        type="checkbox" 
        onChange={this.changeChecked}
        checked={this.state.accepted}
      />
    );
  }
}

export default App;

The resulting behaviour is a correctly updated state on first click, but the checkbox only changes to its 'checked' appearance on the next rerender, eg. a second click.

Why is that? Isn't it the point of controlled ponents to work independently from browser events?

Someone explaining this to me would definitely ease the pain of hours spent boiling down my plex use case. Thank you!

Update: Here's a quick Codepen example demonstrating the odd behaviour. I included an 'unprevented checkbox' and one with a prevented onClick event as parison. Notice how the one with prevented onChange switches its appearance to its actual state as soon as I click a different checkbox.

Share Improve this question edited Nov 19, 2021 at 10:57 gl03 asked Nov 18, 2021 at 15:44 gl03gl03 1,16913 silver badges21 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 5

Checkboxes behave a little differently. As you likely know, the typical use case for preventDefault() is the onSubmit() function of a form where you will do your own AJAX call, and thus want to prevent the default form submission. But with checkboxe (and most inputs) there's a little more involved.

Checked attribute

Per MDN, the checked attribute is "A Boolean attribute indicating whether or not this checkbox is checked by default (when the page loads). It does not indicate whether this checkbox is currently checked: if the checkbox’s state is changed, this content attribute does not reflect the change." In a funny way then, there's a disconnect between the checked attribute, and whether or not the state of the input is checked or not. When it es to React, on each rerender, the checked attribute will reflect the current state, but it's still only a default value in the sense that the input has been newly rendered, and not manipulated since the state last changed.

Native eventListener for <input type="checkbox" />

Also, without getting too off track, the event that natively changes the state on a checkbox input is actually the click event, not the change event. If you were to mess with the listeners and the values of a checkbox input in your browser's js console, you'd see you could manipulate it in a way that the checkbox isn't checked, but the values of the node say otherwise.

Possible solution

Based on the above, in this case you don't want to prevent the default behavior, because the default behavior on the change event doesn't conflict with what you want to do (and for some reason preventing it causes problems). In fact, in the Mozilla docs examples, you'll notice they don't use preventDefault() when updating state on controlled ponents. I wish I had a better understanding of exactly why adding preventDefault() to change handlers for inputs causes problems like this, but hopefully these few little tidbits give some more clarity.

Try moving event.preventDefault() above this.setState line.

发布评论

评论列表(0)

  1. 暂无评论