2

I am using reactjs to try and navigate through a list of components using the keyboard kind of like how you can navigate through facebook using the j and k keys. How can I shift focus to the first component in the list using the j key when I first land on the page and then shift focus between the components after using j and k?

<ul className={s.feed}>
  {this.props.data.map((item, index) => {
    <li key={index} className={s.componentContainer}>
      <Component component={item} />
    </li>
  })}
</ul>

so what the code does is basically generates components into the ordered list and im just wondering how I can shift focus between them with the j and k keys and not using tab.

Philip J
  • 23
  • 5
  • Show us your code. Are you looking for the [focus](https://stackoverflow.com/questions/17500704/javascript-set-focus-to-html-form-element) method? – Jeroen Heier Jul 07 '17 at 03:53
  • I updated it with the code. I was looking into the focus method, but I was wondering if there was a method or anything else where it would move focus to the next item in the list? – Philip J Jul 07 '17 at 16:22

1 Answers1

3

Currently I am working on similar problem.

Suppose you have such state:

items = [
    {
        name: 'a',
        onFocus: true
    },
    {
        name: 'b',
        onFocus: false
    }
];

In you lifecicle methods add and remove enent listeners

componentWillMount() {
    document.addEventListener("keydown", this.handleKeyDown, false);
}
componentWillUnmount() {
    document.removeEventListener("keydown", this.handleKeyDown);
}

here is handleKeyDown - you just set onFocus value in the handler:

handleKeyDown(e) {
    let index = -1;
    const items = this.state.items;
    items.map((item, i) =>{
        if(item.onFocus)index = i;
    });

    switch(e.keyCode) {
        case 74:
            e.preventDefault();
            if(index > 0) i--;
            break;
        case 75:
            e.preventDefault();
            if(index < this.state.items.length - 1) i++;
            break;
    }
    for(let i = 0; i < items.length; i++) {
        items[i].onFocus = i === index;
    }
    this.setState({items});
}

And depending on which element has onFocus set to true - you can set (for example) appropriate classes:

<ul>
  {this.props.data.map((item, i) => {
    <li key={i}>
      <Component component={item} className={item.onFocus ? 'active' : ''} />
    </li>
  })}
</ul>
kurumkan
  • 2,635
  • 3
  • 31
  • 55