Home > Blockchain >  JavaScript redirect sometimes goes to /undefined
JavaScript redirect sometimes goes to /undefined

Time:06-19

I'm using this code to fade-out the website whenever there's a redirect, and it seems to work pretty well most of the time.

var body = document.body;

addEventListener('beforeunload', event => {
    function redirect() {
        location.href = event.target.href;
        body.removeEventListener('transitionend', redirect);
    }           
    body.addEventListener('transitionend', redirect);
    body.style.opacity = 0;
    event.preventDefault();
});

(I have a CSS transition for opacity here)

Occasionally though, maybe once every five times, I get redirected to https://example.com/undefined (example being my website) instead of the correct location. This happens with both relative and absolute URLs. Why is this happening, and why does it only happen sometimes? And, how can I fix it?

Just in case, I'll mention that I'm using an Express.js server here, but the issue doesn't seem to be server-side.

UPDATE:

Apparently, if I remove the redirect function entirely, it still works (and fixes the problem). My current theory is that since it still redirects even with preventDefault() (as @stephancasas mentioned), the transition only happens because the page takes a few fractions of a second to load. My edited code looks like this:

addEventListener('beforeunload', event => {
    body.style.opacity = 0;
});

I still don't completely understand what's going on though, any explanation would be helpful.

CodePudding user response:

This likely won't work or will work very inconsistently. You can't intercept the beforeunload event to do much else other than confirm that the user wants to leave the page (e.g. they've entered form data and would lose it on a reload/redirect).

Per the standard, the event listener's callback should return a string which is to be displayed in the dialog with which the user will be prompted.

This is done with great purpose, as allowing freeform interception of this event could be misused to trap users' browsers on specific locations.

CodePudding user response:

Since your code is using event.target.href, I've assumed you want to set body.style.opacity = 0, when a user clicks a link on the page.

I would prefer attaching event listener on all 'a' tags (it's costly though) as it'll give you better control over 'beforeunload', it's easy to debug and it'll always redirect with correct href.

document.addEventListener('DOMContentLoaded', function() { // Make sure DOM is loaded
    
    // init global vars
    var url = ''; 
    var body = document.body;
    
    function redirect() {
        window.location.href = url; // comment this if you want to debug css change effects before redirecting
        body.removeEventListener('transitionend', redirect);
    }
            
    // Add event listner to transitionend
    // Use webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd or transitionend based on browser
    body.addEventListener('transitionend', redirect);
                
    // Add event listner to all anchor tags on the page
    var aTags = document.querySelectorAll('a'); 
    aTags.forEach(function(a) {
        a.addEventListener('click', e => {          
            var href = e.target.href;
            if(!href || href == window.location.href) { // return, if the target is same url
                // add more validations as per your requirements
                return;
            }
            
            e.preventDefault();
            url = href; // update golbal url var
            body.style.opacity = 0;
            body.style.transition = 'all 0.5s ease'; // this is important for transitionend listner to trigger
        });
    });     
}, false);
  • Related