【Inertia】ブラウザバックでrouterでの自動更新を行う

こんにちは、フリーランスエンジニアの太田雅昭です。

Inertiaでのデータ更新周り

Inertiaでは、主にusePageでデータを処理します。これはレンダリング時にサーバーから直接データをもらえるので、便利です。

ところが色々な問題もあります。今回はブラウザバック周りの問題をあげます。

サーバーでリダイレクトしてみる

アイテムリストを表示しているページから、新しくデータを作成する時に、サーバーサイドで以下のようにリダイレクトしたとします。

public function store(Request $request)
{
    ...
    return to_route('xxx.show', $xxx);
}

無事新しいデータのページにリダイレクトされるのですが、ここからブラウザバックで戻ると、データが更新されず、古い状態の表示がされてしまいます。せっかくデータを追加したのに、追加されていないかのようになってしまいます。

リダイレクトをなくしてみる

それを防ぐため、リダイレクトをなくしてみます。

public function store(Request $request)
{
    ...
    return back();
}

これで、新しくデータを追加したことがアイテムリストに反映されます。場合によってはこれで良いのですが、paginationを使っていると、例えば2ページ目を表示している時にアイテムを追加すると、追加されたアイテムが表示されないといった事象が発生します。

リダイレクトした上で、ブラウザバック時にリロードしてみる

そこで以下のように、ブラウザバック時に自動で更新するようにしてみます。

window.addEventListener('popstate', ()=>{
    window.location.reload();
});

これで、新しく追加したデータのページに移動した上で、ブラウザバックした時には自動更新されるようになりました。ユーザー体験にはだいぶ向上したかと思います。ですが更新表示がスムーズではないため、inertiaの機能でリロードしてみます。

window.addEventListener('popstate', ()=>{
    router.reload();
});

これで良いはず。。。と思ったのも束の間、正常にブラウザバックできません。これは困りました。これまでにあげてきた方法のどれかを選ばないといけないのか、しばらく頭を悩ませていたのですが、以下のようにすることで解決しました。

リダイレクトした上でブラウザバック時にsetTimeoutでInertiaリロードする

window.addEventListener('popstate', ()=>{
    setTimeout(()=>{
        router.reload();
    }, 10);
});

setTimeoutでスレッドを変更することで、routerでも正常にリロードできるようになりました。