Help us understand the problem. What is going on with this article?

pushStateのstateObjでハマった。

More than 5 years have passed since last update.

どもども、フロントはそんなに得意じゃないのですが、かなりハマったバグだったので一応Qiitaに投稿しておこうとおもいます。

pushStateすると、Chromeが謎の挙動

現象はちょっと説明しにくいので割愛しますが、pushStateするとChromeのブラウザバックの挙動が謎の動きをするようになった。

原因を調査していたら、pushStateのstateObjectの扱いが問題だったことがわかったので共有しておきたいと思います。

pushStateとは

詳しくはリンク先を参照してください。

state オブジェクト — state オブジェクトは pushState() によって作成される新しい履歴エントリに関連付けられる JavaScript オブジェクトです。ユーザーが新しいエントリに移動すればいつでも、popstate イベントが発火して、履歴エントリの state オブジェクトのコピーがイベントの state プロパティへと含まれることとなります。

state オブジェクトは何であってもシリアライズされます。Firefox はユーザーのディスクに state オブジェクトを保存し、ユーザーがブラウザを再起動した際に state オブジェクトを復元するため、シリアライズされた状態での state オブジェクトの最大文字数は640000文字と、サイズの制限がされています。シリアライズ後にこの最大文字数を上回ることになる state オブジェクトを pushState() に渡した場合、pushState()は例外を投げます。これを上回るスペースが必要な場合、sessionStorage または localStorage の使用を推奨します。

今回重要なのはココ↓

state オブジェクトは何であってもシリアライズされます。

実際にハマった部分

最初、stateObjをテキストにしていました。

var stateObj = "bar";
history.pushState(stateObj, "page 2", "bar.html");

これでもね、一応期待する挙動は実現できるんですよ。なので特に違和感なくそのまま実装していたんですよね…。

どうやらオブジェクト化しないとダメらしい

  • ↑のところにも書いてあるので当たり前なのだけど、オブジェクトでないとダメみたいでした。
  • オブジェクトならStringオブジェクトとかでもいいのかどうかは未確認

解決後

var stateObj = { foo: "bar" };
history.pushState(stateObj, "page 2", "bar.html");

あー、スッキリ。
ドキュメントはちゃんと見ようね。というお話でした。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away