pushState: what exactly is the state object for?

22,224

Solution 1

Take this small example - run fiddle:

You have a page where a user can select a color. Every time they do, we generate a new history entry:

function doPushState (color) {
    var state = {},
        title = "Page title",
        path  = "/" + color;
    
    history.pushState(state, title, path);
};

We leave the state object blank for now and set the URL to the color name (don't reload the page - that URL doesn't exist, so you will get a 404).

Now click on a red, green and blue once each. Note that the URL changes. Now what happens if you click the back button?

The browser does indeed go back in history, but our page doesn't notice that - the URL changes from '/blue' back to '/green', but our page stays at 'You have selected blue'. Our page has gone out of sync with the URL.

This is what the window.onpopstate event and the state object are for:

  1. We include our selected color in our state object
function doPushState (color) {
    var state = { selectedColor: color }, // <--- here
        title = "Page title",
        path  = "/" + color;
    
    history.pushState(state, title, path);
};
  1. Then we listen for the popstate event, so that we know when we have to update the selected color, which is this:
window.addEventListener('popstate', function (event) {
    var state = event.state;
    
    if (state) {
        selectColor( state.selectedColor );
    }
});

Try the updated example: run fiddle: our page now updates accordingly when the user navigates back through history.

Solution 2

Is a specific and forward looking use case the maintenance of user view and data state in a progressive app using custom elements and templates that are divided up in the view regionally

Imagine a 64 box grid as your view, on a large screen the boxes are 147 ^2 a piece

The url represents 64/ a user ID abs related user data

The web app can then fill its grid with user specific state data

In this use case, one I fully believe is the future, the user wouldn't want to share his or her personal state and data filled view portions

By using previous history states and their related 650k of data

A whole, complex app can be, reassembled from browser history and location, including state, using a few well known sort approaches.

It's cool

Solution 3

It gives you the option to not store all of the data in the URL if you don't want to.

Open your console and try this:

First make a listener

window.addEventListener('popstate', function (event) {    
    console.log(`You first visited this page at ${event.state.time}`)
});

Then push a state in a console a few times, waiting a bit between each one to get different times (Don't copy and paste the whole chunk. Copy the first line and submit it to the console a few times):

history.pushState({time:new Date().getTime()},'','/foo');
history.pushState({time:new Date().getTime()},'','/foo');
history.pushState({time:new Date().getTime()},'','/foo');
history.pushState({time:new Date().getTime()},'','/foo');
history.pushState({time:new Date().getTime()},'','/foo');
history.pushState({time:new Date().getTime()},'','/foo');

Now press your back button in the browser and view the console.

The state object is probably not ideal for most use cases in the real world - usually you want the URL to completely describe what you're about to see.

Share:
22,224
campari
Author by

campari

Updated on July 05, 2022

Comments

  • campari
    campari almost 2 years

    I've read a dozen of times now that the state object could exists of multiple key|value pairs and that it is associated with the new history entry. But could someone please give me an example of the benefits of the state object? Whats the practical use of it? I can't imagine why not just typing in {}

  • Alvaro
    Alvaro over 10 years
    Thanks for the illustrative example
  • Helder Roem
    Helder Roem about 10 years
    This is all well and good but what happens when my user shares the myawesomewebsite.com/blue uri with their friend saying look at how awesome the blue theme is on this website and the theme isn't applied because the friend doesn't have the state object stored in their browser, I still have to have some other mechanism in my app to restore state for first time visitors to a uri making this functionality redundant or am I missing something here?
  • Vinicius Pinto
    Vinicius Pinto over 9 years
    @HelderRoem you're right in that your app has to provide the initial state, but it's not redundant because with the state on the client the app can avoid hitting the server every time the user goes back to /blue
  • ma11hew28
    ma11hew28 over 8 years
    Why not just use the path, e.g., selectColor(location.pathname), instead of the state object?
  • janfoeh
    janfoeh over 8 years
    @MattDiPasquale just to show that the state object supports complex objects, not just primitives.
  • Joshua Frank
    Joshua Frank over 8 years
    @janfoeh: When I try this in Firefox v42.0, the state is preserved, but the url doesn't update.
  • Elijah Lynn
    Elijah Lynn almost 8 years
    URL isn't updating anymore. Chrome 51 on Ubuntu.
  • janfoeh
    janfoeh almost 8 years
    @ElijahLynn works for me on Chrome 52 / OS X. Do you mean my fake URL bar or the real one? Any suspicious error messages in your developer console?
  • Elijah Lynn
    Elijah Lynn almost 8 years
    I mean the real URL bar. No errors in the developer console.
  • janfoeh
    janfoeh almost 8 years
    @ElijahLynn the real URL bar doesn't change, because jsFiddle changed their setup some time after I wrote the example. The fullscreen display now runs in an <iframe>, so you can't see the childs' URL anymore — only the embedding parents' one. That is why I added the fake URL bar afterwards.
  • ANewGuyInTown
    ANewGuyInTown almost 6 years
    Is the state per URL? I mean are the state available to all URL or only to the URL associated?
  • janfoeh
    janfoeh almost 6 years
    @ANewGuyInTown the state is only available to the document that created it. The 'Notes' section in the MDN article on Window.history might answer your question.
  • 0ddlyoko
    0ddlyoko over 5 years
    I just want to say your code doesn't work if you click on a color then you go back, it still saying "You have selected green" and not "You have selected no color", do you have any fix ?
  • aderchox
    aderchox over 3 years
    Please get hired by the MDN. You've got 103 votes already :D