React-modal: Modal loses focus when focussed element is removed from DOM

Created on 25 Aug 2017  路  6Comments  路  Source: reactjs/react-modal

Summary:

Steps to reproduce:

  1. Focus an element inside the modal (e.g. a link)
  2. Remove it from the DOM (e.g. when the link is clicked, the modal contents re-render to the new route)
  3. Press escape

Expected behavior:

The modal should call onRequestClose, but it doesn't. The active element is the body.

Link to example of issue:

https://jsfiddle.net/ufgse6np/5/embedded/result/

Code: https://jsfiddle.net/ufgse6np/5/

bug

Most helpful comment

My workaround:

  componentDidUpdate(prevProps) {
    const { location } = this.props;
    const hasRouteChanged = location.key !== prevProps.location.key;
    if (this.reactModalRef !== undefined && this.reactModalRef !== null && hasRouteChanged) {
      // There is a bug in React Modal whereby the modal loses focus when the focussed element is
      // removed from the DOM. For example, this might happen when clicking a link inside the modal,
      // which would then replace the modal contents. As a result, the modal would not respond to
      // the escape key.
      // As a workaround, we restore focus to the modal whenever the modal upates due to a route
      // change.
      // https://github.com/reactjs/react-modal/issues/486
      this.reactModalRef.portal.content.focus();
    }
  }

All 6 comments

My workaround:

  componentDidUpdate(prevProps) {
    const { location } = this.props;
    const hasRouteChanged = location.key !== prevProps.location.key;
    if (this.reactModalRef !== undefined && this.reactModalRef !== null && hasRouteChanged) {
      // There is a bug in React Modal whereby the modal loses focus when the focussed element is
      // removed from the DOM. For example, this might happen when clicking a link inside the modal,
      // which would then replace the modal contents. As a result, the modal would not respond to
      // the escape key.
      // As a workaround, we restore focus to the modal whenever the modal upates due to a route
      // change.
      // https://github.com/reactjs/react-modal/issues/486
      this.reactModalRef.portal.content.focus();
    }
  }

@OliverJAsh This is an interesting case. Probably the best way to deal with this is to provide a method so the user can call to give focus back to the modal (inspired by you solution and probably better then expose the focusable api helpers/focusManager.js).

modal_instance.focus(); // give the focus t the modal and 
modal_instance.focusContent(); // give the focus to the first focusable children.

Any thoughts?

Ideally this would be handled by the component so consumers don't have to manually manage the focus. Is there any way in your mind to do this? I know the removed element will fire a blur event鈥攊s that something we could use?

I don't think there is something we can on the modal side. If we try to refocus on blur, we may fall into some problems like "jump back to the first element" (if removed a nth element). Perhaps, it would be better to let the user decide about this and when. We can provide some tools tough.

Aha, that makes sense, because focus causes the browser to scroll. In that case, I agree 馃憤

This was useful for me, thanks! I was having a possibly related problem with a button in the modal content which was disabled but still had the focus.

Was this page helpful?
0 / 5 - 0 ratings