skip to Main Content

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 class="wrapper">
        <div class="container">
          <div class="item" tabIndex="1">
            item 1
          </div>
          <div class="item" tabIndex="3">
            item 2
          </div>
          <div class="item" tabIndex="2">
            item 3
          </div>
          <div class="item" tabIndex="5">
            item 4
          </div>
          <div class="item" tabIndex="4">
            item 5
          </div>
          <div class="item" tabIndex="7">
            item 6
          </div>
          <div class="item" tabIndex="6">
            item 7
          </div>
          <div class="item" tabIndex="9">
            item 8
          </div>
          <div class="item" tabIndex="8">
            item 9
          </div>
          <div class="item" tabIndex="10">
            item 10
          </div>
        </div>
      </div>

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

2

Answers


  1. 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.

    Login or Signup to reply.
  2. 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;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search