Home > Blockchain >  Reactjs. I have an arrow key navigation problem
Reactjs. I have an arrow key navigation problem

Time:12-09

I'm trying to do xmb (psp/ps3) menu in react and i have a problem. The problem is that items scroll through the next item. For example: Item 1 scrolls to Item 3 (Item 2 is skipped although item 2 should come after 1 item) and in back From Item 3 to 1. How Can i fix it?

The demo: https://codesandbox.io/embed/relaxed-cohen-05tvt6?fontsize=14&hidenavigation=1&theme=dark

I tried some ways

      $(".container").on("keydown", function (e) {
        if (e.which === arrowKeys.left) {
          _position = --_position / _length;
        }

        if (e.which === arrowKeys.right) {
          _position =   _position / _length;
        }

        move();
      });
      $(".container").on("keydown", function (e) {
        if (e.which === arrowKeys.left) {
          _position = (1-_position) % _length;
        }

        if (e.which === arrowKeys.right) {
          _position = (1-_position) % _length;
        }

        move();
      });
      $(".container").on("keydown", function (e) {
        if (e.which === arrowKeys.left) {
          _position = --_position % (_length-1);
        }

        if (e.which === arrowKeys.right) {
          _position =   _position % (_length-1);
        }

        move();
      });

And i edited in HTML

          <div >
        <div >
          <div  tabIndex="1">
            item 1
          </div>
          <div  tabIndex="3">
            item 2
          </div>
          <div  tabIndex="2">
            item 3
          </div>
          <div  tabIndex="5">
            item 4
          </div>
          <div  tabIndex="4">
            item 5
          </div>
          <div  tabIndex="7">
            item 6
          </div>
          <div  tabIndex="6">
            item 7
          </div>
          <div  tabIndex="9">
            item 8
          </div>
          <div  tabIndex="8">
            item 9
          </div>
          <div  tabIndex="10">
            item 10
          </div>
        </div>
      </div>

But none of this ways worked. How can i fix it?

CodePudding user response:

That is because you are using <StrictMode> in the index.js file.

To help surface these issues, React 18 introduces a new development-only check to Strict Mode. This new check will automatically unmount and remount every component, whenever a component mounts for the first time, restoring the previous state on the second mount.

This will re-run some lifecycle methods (like componentDidMount) and so it will add your key handler twice.


You could ofcource make your code more defensive and remove all the global event handlers once the component is unmounted.

CodePudding user response:

I think using React instead of Jquery to listen to events is the best way.

These codes only demo how to refactor the keydown event.

https://codesandbox.io/s/awesome-framework-jsbrx2?file=/src/App.js

import React from "react";
import $ from "jquery";
import "./style.css";

class App extends React.Component {
  _position = 1;
  _length = 0;
  arrowKeys = { left: 37, up: 38, right: 39, down: 40 };

  componentDidMount() {
    const componentRef = this;
    (function () {
      var _items = $(".container").find(".item");
      componentRef._length = _items.length;

      $(".container").on("focus", ".item", function () {
        componentRef._position = $(this).index();
      });

      $(".container").on("click", ".item", function () {
        componentRef.move();
      });
    })();
  }

  move() {
    $(".container").find(".item").get(this._position).focus();
    $(".wrapper").css("transform", function (a, b) {
      var left = a - 3 * this._position   "%";
      return "translate3d("   left   ",0,0)";
    });
  }

  customKeydown = (e) => {
    if (e.which === this.arrowKeys.left) {
      this._position = --this._position % this._length;
    }

    if (e.which === this.arrowKeys.right) {
      this._position =   this._position % this._length;
    }

    this.move();
  };

  render() {
    return (
      <div className="wrapper">
        <div className="container" onKeyDown={this.customKeydown}>
          <div className="item" tabIndex="1">
            item 1
          </div>
          <div className="item" tabIndex="2">
            item 2
          </div>
          <div className="item" tabIndex="3">
            item 3
          </div>
          <div className="item" tabIndex="4">
            item 4
          </div>
          <div className="item" tabIndex="5">
            item 5
          </div>
          <div className="item" tabIndex="6">
            item 6
          </div>
          <div className="item" tabIndex="7">
            item 7
          </div>
          <div className="item" tabIndex="8">
            item 8
          </div>
          <div className="item" tabIndex="9">
            item 9
          </div>
          <div className="item" tabIndex="10">
            item 10
          </div>
        </div>
      </div>
    );
  }
}
export default App;
  • Related