Search code examples
javascriptfetch-apibrowser-historyhtml5-history

Making smooth page transitions with fetch and History API


I am trying to make a website that has smooth page transitions using document.write after sending a fetch to the page and using history.pushState. It switches the default behavior of all anchor tags, and when going to another page, it works, but when navigating back it doesn't.

<script defer>
    Array.from(document.getElementsByTagName('a')).forEach(function(el) {
        el.addEventListener('click', function(ev) {
            ev.preventDefault()
            fetch(el.getAttribute('href')).then(function(res) {
                if (res.ok) {
                    return res.text()
                } else {
                    return document.documentElement.innerHTML
                }
            }).then(function(text) {
                    history.pushState({
                        prev_url: window.location.href
                    }, "", el.getAttribute('href'))
                    document.write(text)
                })
            })
        })


    window.addEventListener('popstate', function(ev) {
        console.log(ev.state)
        fetch(ev.state.prev_url).then(function(res) {
                return res.text()
            }).then(function(text) {
                document.write(text)
                history.pushState({
                    prev_url: window.location.href
                }, "", el.getAttribute('href'))
            })
    })
</script>

I tried this.


Solution

  • I think I misunderstood what the event.state refers to. It refers to the top stack after the popstate, not the state that was popped.

    This stackoverflow answer was very helpful: window.onpopstate, event.state == null?, the answer by MQ87 explained it.

    My solution was to add

    history.replaceState({
        prev_url: window.location.href
    }, "")
    

    at the beginning of my code.

    It builds the state without the user having to navigate back twice.