How to Detect If Url Has Changed After Hash in JavaScript

How to detect if URL has changed after hash in JavaScript

In modern browsers (IE8+, FF3.6+, Chrome), you can just listen to the hashchange event on window.

In some old browsers, you need a timer that continually checks location.hash. If you're using jQuery, there is a plugin that does exactly that.

Example

Below I undo any URL change, to keep just the scrolling:

<script type="text/javascript">
if (window.history) {
var myOldUrl = window.location.href;
window.addEventListener('hashchange', function(){
window.history.pushState({}, null, myOldUrl);
});
}
</script>

Note that above used history-API is available in Chrome, Safari, Firefox 4+, and Internet Explorer 10pp4+

How to detect URL changes in SPA

Under normal circumstances, there isn't an event when the URL changes. You are loading a new document (although you have load and so on)

If you are setting a new URL with JavaScript (i.e. with pushState) then there isn't an event, but you don't need one because you're already explicitly writing code around it, so you just add whatever else you need to that code.

You'll get a popstate event if the URL changes back though your pushState history via the browser back button or similar.


Consequently, there is no good generic way to hook into every SPA. The closest you could come would be to use setInterval and inspect the value of location.href to see if it changed since the last inspection.

Detect an URL change in a SPA

This https://stackoverflow.com/a/41825103/7042552 did the job for me, unbelievable we still have to use these hacks in 2018.

How to detect change in the URL hash in Next.js?

You can listen to hash changes using hashChangeStart event from router.events.

const Test = () => {
const router = useRouter();

useEffect(() => {
const onHashChangeStart = (url) => {
console.log(`Path changing to ${url}`);
};

router.events.on("hashChangeStart", onHashChangeStart);

return () => {
router.events.off("hashChangeStart", onHashChangeStart);
};
}, [router.events]);

return (
<>
<Link href="/#some-hash">
<a>Link to #some-hash</a>
</Link>
<Link href="/#some-other-hash">
<a>Link to #some-other-hash</a>
</Link>
</>
);
};

If you're not using next/link or next/router for client-side navigation (not recommended in Next.js apps), then you'll need to listen to the window's hashchange event.

Your useEffect would look like the following.

useEffect(() => {
const onHashChanged = () => {
console.log('Hash changed');
};

window.addEventListener("hashchange", onHashChanged);

return () => {
window.removeEventListener("hashchange", onHashChanged);
};
}, []);

Detect specific part of url change

Do it with jQuery, works fine for me.

$(window).on("hashchange", function(){
alert('change');
});

Tested whith mySite.fr/#toto and mySite.fr/#tototata
Event was fired when anchor changed.

How can I detect changes in location hash?

The only way to really do this (and is how the 'reallysimplehistory' does this), is by setting an interval that keeps checking the current hash, and comparing it against what it was before, we do this and let subscribers subscribe to a changed event that we fire if the hash changes.. its not perfect but browsers really don't support this event natively.


Update to keep this answer fresh:

If you are using jQuery (which today should be somewhat foundational for most) then a nice solution is to use the abstraction that jQuery gives you by using its events system to listen to hashchange events on the window object.

$(window).on('hashchange', function() {
//.. work ..
});

The nice thing here is you can write code that doesn't need to even worry about hashchange support, however you DO need to do some magic, in form of a somewhat lesser known jQuery feature jQuery special events.

With this feature you essentially get to run some setup code for any event, the first time somebody attempts to use the event in any way (such as binding to the event).

In this setup code you can check for native browser support and if the browser doesn't natively implement this, you can setup a single timer to poll for changes, and trigger the jQuery event.

This completely unbinds your code from needing to understand this support problem, the implementation of a special event of this kind is trivial (to get a simple 98% working version), but why do that when somebody else has already.

Detect changes on the url

You need to store the URL when the page loads as a starting point and setInterval to check for changes and modify based on that.

The following code does this check twice a second (500ms):

// store url on load
let currentPage = location.href;

// listen for changes
setInterval(function()
{
if (currentPage != location.href)
{
// page has changed, set new page as 'current'
currentPage = location.href;

// do your thing..
}
}, 500);


Related Topics



Leave a reply



Submit