Gabi C
Gabi C

Reputation: 481

Focus on div without click in React to enable keyboard navigation on a module

I am coding an image gallery from scratch in React, when clicking on an image, a modal pops up (separate component from my gallery component). I want to navigate between the pictures with left and right arrow, not just with the added arrows on the screen (onclick) but at the moment it only focuses on the modal when I click on it once, then I can navigate with the keyboard too (onKeyDown).

I have added tabIndex="0" to my div, but I still need to click on the div once to focus on it.

<div tabIndex="0" onKeyDown={(event) => this.onKeyNavigation(event, ImageUrl, currentIndex, ImageUrls)}>

onKeyNavigation = (event, ImageUrl, currentIndex, ImageUrls) => {

if ((event.keyCode) === 39) {
    this.props.loadNext(ImageUrl, currentIndex, ImageUrls)
  }
  else if ((event.keyCode) === 37) {
    this.props.loadPrevious(ImageUrl, currentIndex, ImageUrls)
  }
  else if ((event.keyCode) === 27) {
    this.props.onClose()
  }
 }

Upvotes: 6

Views: 11835

Answers (3)

TazExprez
TazExprez

Reputation: 335

dcastrodale your answer helped me a lot, but for some reason this would not work until I placed the ref in the componentDidMount() inside of a setTimeout(). This is what I did to focus on a specific div when the page loaded.

//This line was added in the constructor().
this.drumMachineAndOuterControllerRef = React.createRef();

//This is how my componentDidMount() looks like.
componentDidMount() {
  setTimeout(() => {
    this.drumMachineAndOuterControllerRef.current.focus();
  }, 5);
}

//This is the div that is put in focus after the page loads.
<div id="drum-machine-and-outer-controller" tabIndex="0" onKeyDown={this.keyboardPress} ref={this.drumMachineAndOuterControllerRef}>

This works great for me and I could even press the button elements with the keyboard without the mouse pointer ever entering the browser window.

Thanks again dcastrodale! Your answer guided me in the right direction.

Upvotes: 0

Gabi C
Gabi C

Reputation: 481

So the solution was:

componentDidUpdate(){ this.focusRef.current.focus(); }

Upvotes: 0

dcastrodale
dcastrodale

Reputation: 97

You'll need to fire a focus() event on the <div> you want to have focus after it has rendered.

The easiest way to do this is to use React's built-in lifecycle methods. First, create a ref for the element you want to have focus (in this case, the div listening for keyDown events). Then, you can call focus() on that node in your component's componentDidMount() method:

class ImageGallery extends React.Component {
    construtor(){
        super();

        // Create the ref in the constructor
        this.focusRef = React.createRef();
    }

    /* your other methods here */

    componentDidMount(){
        // Focus on the rendered div using the DOM focus() method
        this.focusRef.focus();
    }

    render(){
        // Set the ref in your render() method
        return(<div ref={this.focusRef} onKeyDown={this.handle}></div>);
    }
}

Upvotes: 2

Related Questions