Navigate Modal in React using onKeyDown and Portal do I need onFocus?

Hi all,

I want to be able to give the user the ability to use the keyboard left/right arrow keys to move between images that are loaded in a modal. The modal is mounted using ReactDOM.createPortal(). An array of images are coded to iterate using onClick events on next/previous react class components.

I think that when the modal mounts into the Portal the focus is still on the app’s #root div, therefore maybe this is why keyboard events are not being registered? OnFocus as an event I believe in React will not move focus onto a DOM element that I want to target, i.e. the Modal/Portal, is this true? Does this only gives access to a function on focus and on blur?

Is a workaround, or correct way, to put the onKeyDown event on the main App and then only listen to it when the Modal state is true, and the if the key values are equal to “ArrowLeft” or “ArrowRight”? Or should I use componentDidMount/componentWillUnmount for the modal to use vanilla JS to add an event listener to the window?

Kirupa, your synthetic events in react page helps, but still I’m totally confused what direction to go in. JavaScript events on DOM elements feel very much easier to logically code (even with their quirks and browser incompatibilities) than React synthetic events!

Thank you to any who may be able to point me towards figuring this out :slight_smile:

The onClick events work just fine, right? When you click on the modal with your mouse and then use the arrow keys, are you able to navigate as expected?

:slight_smile:

Hi, thank you for your reply.

Yes, the onClick events work perfect, though that seems a given with event.handleOnClick as the mouse click brings the element into focus. I never thought to add the onKeyDown events to the same components that hold the onClick events. I’ll give that a try. Sounds like I should get a response to the keyDown after an onClick. I’m not sure once I get to this how these forward/next components would receive focus without some mouse action first? When the router view loads the modal into the portal, using the tab key will only tab through the elements below, it will not tab up to the overlaying modal.

I will attempt some changes tomorrow and let you know :slight_smile:

Solved it! By putting the event on the next/previous divs I set out to troubleshoot the problem!

First I found that onKeyPress is not the way to go in this situation, onKeyDown triggers an event.

Then I found that keyboard num, extra keys, and arrow keys don’t give string or number results with all React properties applied to the event. event.key finally gave me “ArrowLeft”/“ArrowRight

This only works when the div is given focus. I added tabIndex=“0” which helps, but still with the modal mounting in a portal a user needed to click the page. Also used the CSS attribute outline: 0; to get rid of that pesky blue focus line!

I used componentDidMount/componentWillUnmount to target the div (I ended up just using the one containing modal overlay div to attach the onKeyDown event listener) and so now on mount/unmount the div has focus()/blur()

I was able to then simply call the handleNext/handlePrev functions from the onClick events and all works perfectly!

Thanks for that little push Kirupa, it got me to the right mindset to solve this. :slight_smile:

1 Like