React Redux onBlur event not firing in Safari and Firefox

纵然是瞬间 提交于 2021-02-08 10:16:48

问题


This seems to work perfectly in Chrome and Edge. I have a tooltip that needs to pop up onClick of the button, and then disappear onBlur. For some reason the onBlur event does not fire at all on Safari or Firefox.

I've tried logging to the console in handleBlur and it does not get that far, it is as if onBlur does not exist in this context.

class Tooltip extends Component {
  componentWillUnmount() {
    this.closeActiveTooltip();
  }

  handleKeyPress = (event) => {
    if (event.keyCode === 27) { // Esc key
      this.closeActiveTooltip();
    }
  }

  handleBlur = () => {
    if (this.props.activeTooltip === this.props.name) {
      // setTimeout is for link click
      setTimeout(this.closeActiveTooltip, 100);
    }
  }

  closeActiveTooltip = () => {
    const { activeTooltip, closeTooltip } = this.props;

    if (activeTooltip) {
      closeTooltip(activeTooltip);
    }
  }

  render() {
    const {
      isOpen,
      text,
      link,
      position,
    } = this.props;
    const popupClassName = getClassNameFor(s, 'popup', `${isOpen && 'open'} ${position}`);
    const linkElement = (
      <div className={s.link}>
        <a
          href={link}
          target="_blank"
          rel="noopener noreferrer"
        >
          More info here
        </a>
      </div>
    );

    return (
      <button
        type="button"
        className={s.root}
        onClick={this.props.toggleTooltip}
        onBlur={this.handleBlur}
        onKeyDown={this.handleKeyPress}
      >
        <svg className={s.icon}>
          <use xlinkHref="#more-info" />
        </svg>
        <div className={popupClassName}>
          {text}
          {link && linkElement}
        </div>
      </button>
    );
  }
}

回答1:


All I know is that I could never get an element (most likely an <input />) focused on mount with React, probably because of render()s, so I use setTimeout(() => input.focus(), 0) to make it async. So, it seems there are issues with focus handling...

A simple workaround would be:

<button
    onClick={this.handleAction}
    onMouseDown={this.handleFocus}
    onMouseUp={this.handleBlur} />

But when user release the mouse button out of the button, you'll never trigger the onMouseUp.

A better workaround consists in simulating a click out:

class Tooltip extends Component {
    componentDidMount() {
        document.body.addEventListener('click', this.handleClickOut, false);
    }

    componentWillUnmount() {
        document.body.removeEventListener('click', this.handleClickOut, false);
    }

    handleClickOut = event => {
        if(event.target != this.refs.btn) { // Actually more complicated, event.target can be a child of button (icon, span, etc)
            this.handleBlur();
        }
    }

    handleBlur() {}

    render() {
        return (
            <button
                ref='btn'
                type="button"
            >
                {text}
            </button>
        );
    }
}

possibly with a component that wraps your button

<ClickOut onClickOut={this.handleBlur}>
    <button
        onClick={this.handleAction}
        onMouseDown={this.handleFocus} />
</ClickOut>

Any time you click on your document, if target is not <button /> or one of its child nodes, trigger the click out pseudo event



来源:https://stackoverflow.com/questions/44431931/react-redux-onblur-event-not-firing-in-safari-and-firefox

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!