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

javascript - React prevent onClick firing when onFocus fires - Stack Overflow

programmeradmin4浏览0评论

My field onClick event toggles a dropdown, the onFocus event opens it.
When the onFocus event is fired the onClick event is fired afterwards and closes the newly opened dropdown. How can I prevent firing on Click in Case onFocus fired?

preventDefault and stopPropagation do not work, both events are always fired

<TextInputV2
  label={label}
  onChange={handleInputOnChange}
  onClick={handleOnClick}
  onFocus={handleOnFocus}
  onKeyUp={handleInputOnKeyUp}
  readOnly={!searchable}
  value={inputValue}
/>

.......

  const handleOnFocus = (event: React.FocusEvent): void => {
    if (!isOpen) {
      changeIsOpen(true)
    }
  }

  const handleOnClick = (event: React.SyntheticEvent): void => {
    if (!searchable) {
      toggleOpen()
    }
  }

My field onClick event toggles a dropdown, the onFocus event opens it.
When the onFocus event is fired the onClick event is fired afterwards and closes the newly opened dropdown. How can I prevent firing on Click in Case onFocus fired?

preventDefault and stopPropagation do not work, both events are always fired

<TextInputV2
  label={label}
  onChange={handleInputOnChange}
  onClick={handleOnClick}
  onFocus={handleOnFocus}
  onKeyUp={handleInputOnKeyUp}
  readOnly={!searchable}
  value={inputValue}
/>

.......

  const handleOnFocus = (event: React.FocusEvent): void => {
    if (!isOpen) {
      changeIsOpen(true)
    }
  }

  const handleOnClick = (event: React.SyntheticEvent): void => {
    if (!searchable) {
      toggleOpen()
    }
  }
Share Improve this question edited Sep 2, 2019 at 15:55 Brian Tompsett - 汤莱恩 5,89372 gold badges61 silver badges133 bronze badges asked Sep 2, 2019 at 11:15 jeffjeff 1,1972 gold badges19 silver badges47 bronze badges 2
  • is there any codepen available? – Harish Commented Sep 2, 2019 at 11:29
  • The issue is that you don't stop event to be propagated. In case of the click both onClick and onFocus will be fired if you will not stop event propagation. See: stackoverflow./questions/282245/dom-event-precedence – Maciej Trojniarz Commented Sep 2, 2019 at 11:32
Add a ment  | 

2 Answers 2

Reset to default 16

You will want to change onClick to onMouseDown. Since event order is

  • mousedown
  • change (on focused input)
  • blur (on focused element)
  • focus
  • mouseup
  • click
  • dblclick

from: this answer

You want to preventDefault/stoPropagation BEFORE the focus event, which means you have to use "onMouseDown" to properly stop it before the focus event get triggered.

In your case it would be:

<TextInputV2
  label={label}
  onChange={handleInputOnChange}
  onMouseDown={handleOnClick}
  onFocus={handleOnFocus}
  onKeyUp={handleInputOnKeyUp}
  readOnly={!searchable}
  value={inputValue}
/>
 const handleOnClick = (event) => {
    event.preventDefault()
    event.stopPropagation()
  if (!searchable) {
   toggleOpen()
  }
}

https://jsfiddle/reactjs/69z2wepo/

class Hello extends React.Component {
    constructor(props) {
    super(props);
    this.state = {
        text: 'hello'
    }

    this.lastFocus = 0;
  }

  handleOnClick(ev) {
    const now = new Date().getTime();
    console.log('diff since lastFocus');
    console.log(now - this.lastFocus);
    if (now - this.lastFocus < 200) {
        return;
    }
    const newText = this.state.text + 'c';
    this.setState({text:newText})
  }

  handleOnFocus(ev) {
    this.lastFocus = new Date().getTime();

    const newText = this.state.text + 'f';
    this.setState({text:newText});
  }

  render() {
    return <div>
      <input name="" id="" cols="30" rows="10"
        value={this.state.text}

         onClick={this.handleOnClick.bind(this)}
          onFocus={this.handleOnFocus.bind(this)}
      ></input>
    </div>;
  }
}

ReactDOM.render(
  <Hello name="World" />,
  document.getElementById('container')
);

You store the time of your lastFocus -- not in this.state because that updates asynchronously and you cannot rely on that being updated in the onClick handler by calling setState in the onFocus handler. You put it directly on the instance and update it directly.

You can just use a rule of thumb that says if the last focus was within 200ms, then this onClick handler is from the same event as the onFocus handler, and therefore not run the rest of your onClick handler.

My fiddle is not obviously your entire use case, I'm just adding f on focus and c on click to the input text.

发布评论

评论列表(0)

  1. 暂无评论