skip to Main Content

I get the following error when I click:

Uncaught TypeError: can't access private field or method: object is not the right class
    #clickEventHandler index.js:67
    enable index.js:45

I don’t get any errors in my IDE and I don’t understand what might be wrong.

Relevant code:

InteractionsManager

class InteractionsManager {
    #putHandler
    #eventListener

    constructor(putCallback) {
        this.#putHandler = new PutHandler(putCallback)
        this.#eventListener = null
    }

    /**
     * starts listening to "click" event
     */
    enable() {
line 45:        this.#eventListener = document.body.addEventListener("click", this.#clickEventHandler)
    }

    /**
     * 
     * @param {MouseEvent} e 
     */
    #clickEventHandler(e) {
        const mousePos = getMousePos(e);

line 67:        this.#putHandler.putTHandler(mousePos)
    }
}

PutHandler

class PutHandler {
    putTHandler(mousePos) {
        
    }
}

Any idea what might be wrong?

2

Answers


  1. Edit your enable function as follows:

    enable() {
        this.#eventListener = document.body.addEventListener("click", this.#clickEventHandler.bind(this))
    }
    

    When you pass a method reference like this.#clickEventHandler directly, the event listener does not know about the class instance that it belongs to, causing this inside #clickEventHandler to point to the event target (document.body in this case). By binding this explicitly (with .bind()), you ensure that this still refers to the instance of InteractionsManager when the method is called.

    Login or Signup to reply.
  2. Regarding the OP’s comment targeting my above remark …

    @Amir … In addition to burcu’s answer, are you aware that the return value of addEventListener equals the undefined value? Thus this.#eventListener is of no further use. – Peter Seliger

    @PeterSeliger Oh, thanks, now I don’t know how to remove it later. document.body.removeEventListener("click", this.#clickEventHandler) doesn’t seem to be working. – Amir

    … a possible solution just needs to take burcu’s bind approach a little further …

    // `PutHandler` module scope.
    
    /*export */ class PutHandler {
    
      putTHandler(mousePos) {
    
      }
    }
    // end - `PutHandler` module scope.
    
    
    // `InteractionsManager` module scope.
    
    /* import { getMousePos } from './helpers'; */
    /* import { putCallback } from './helpers'; */
    
    /* import { PutHandler } from './handlers'; */
    
    function clickEventHandler(putTHandler, evt) {
    
      // - a single autonomous handler function designed to be
      //   bound with (an) argument/s only is all that's needed.
    
      putTHandler(getMousePos(evt));
    }
    
    
    /* export */class InteractionsManager {
    
      #putHandler;
      #handleClick;
    
      constructor(putCallback) {
        this.#putHandler = new PutHandler(putCallback);
      }
    
      enable() {
        this.#handleClick =
          clickEventHandler.bind(null, this.#putHandler.putTHandler);
        
        document.body.addEventListener('click', this.#handleClick);
      }
      disable() {
        document.body.removeEventListener('click', this.#handleClick);
      }
    }
    // end - `InteractionsManager` module scope.
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search