skip to Main Content

I have a lib which is added in a SPA project which uses router.push(which will eventually call window.history.pushState) to make the url changes.

However I need my lib to be able to listen to these changes, however since it is an external SPA my lib cant get to know when these changes are made, since pushState doesn’t trigger any event.

So, i figured a good way would be to replace the window.history.pushState with a function of mine so that I could send an event once it was triggered.

Here is what I did:

const pushState = window.history.pushState;

window.history.pushState = (state, unused, url) => {
    // just some code to trigger an event I can later intercept:
    const event = new Event("someEvent"); 
    window.dispatchEvent(event);

    // calls the original function, so that everything could be transparent
    return pushState(state, unused, url);
};

However I keep getting a TypeError: Illegal invocation at window.history.pushState error and cant figure out what I am doing wrong..

Can anybody help me?

2

Answers


  1. Illegal invocation happens when a method is taken out of its original context and used somewhere else. Heres a good read.

    In your case pushState is a method of window.history, so it expects to always be called in the context of window.history.

    Heres how you could do it:

    const pushState = window.history.pushState;
    
    window.history.pushState = function(state, unused, url) {
        const event = new Event("someEvent"); 
        window.dispatchEvent(event);
        return pushState.call(window.history, state, unused, url);
    };
    
    Login or Signup to reply.
  2. You can use Function#bind to set the proper this value for the function.

    const pushState = history.pushState.bind(history);
    // the rest of the code remains the same...
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search