I have build a simple component with a single text input and below of that a list (using semantic ui).
Now I would like to use the arrow keys to navigate through the list.
Selection would mean to add the class active
to the item or is there a better idea for that?
export default class Example extends Component { constructor(props) { super(props) this.handleChange = this.handleChange.bind(this) this.state = { result: [] } } handleChange(event) { // arrow up/down button should select next/previous list element } render() { return ( <Container> <Input onChange={ this.handleChange }/> <List> { result.map(i => { return ( <List.Item key={ i._id } > <span>{ i.title }</span> </List.Item> ) }) } </List> </Container> ) } }
Learn more at the React docs. If you use arrow functions within render , each call to render will create new function objects. If you then pass these functions to child elements via props , optimizations based on PureComponent or shouldComponentUpdate will fail (as the arrow function props will change on every render).
Displaying items from a list of objects in React is very simple. We can iterate over a list of objects using the . map() method in React JSX. Here is the example in which we mapped a list of objects and displayed them in the React app.
Try something like this:
export default class Example extends Component { constructor(props) { super(props) this.handleKeyDown = this.handleKeyDown.bind(this) this.state = { cursor: 0, result: [] } } handleKeyDown(e) { const { cursor, result } = this.state // arrow up/down button should select next/previous list element if (e.keyCode === 38 && cursor > 0) { this.setState( prevState => ({ cursor: prevState.cursor - 1 })) } else if (e.keyCode === 40 && cursor < result.length - 1) { this.setState( prevState => ({ cursor: prevState.cursor + 1 })) } } render() { const { cursor } = this.state return ( <Container> <Input onKeyDown={ this.handleKeyDown }/> <List> { result.map((item, i) => ( <List.Item key={ item._id } className={cursor === i ? 'active' : null} > <span>{ item.title }</span> </List.Item> )) } </List> </Container> ) } }
The cursor keeps track of your position in the list, so when the user presses the up or down arrow key you decrement/increment the cursor accordingly. The cursor should coincide with the array indices.
You probably want onKeyDown
for watching the arrow keys instead of onChange
, so you don't have a delay or mess with your standard input editing behavior.
In your render loop you just check the index against the cursor to see which one is active.
If you are filtering the result set based on the input from the field, you can just reset your cursor to zero anytime you filter the set so you can always keep the behavior consistent.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With