LoginSignup
7
6

More than 5 years have passed since last update.

nuxtでナビゲーションガード時、リダイレクトしてもlayoutが変わらない問題

Posted at

TL;DR

contextnuxtStatelayout プロパティがあるので、そこにlayout値をぶっこむ!

前提

nuxt.jsでユーザー認証ガードをしなくちゃいけないけれども、LocalStorageに情報保持しなくちゃいけないときとかに、
非SSR な plugin をつくって ナビゲーションガード 設定することあると思います。
さらには非同期な処理も叩かなくてはいけないから、async/await にしちゃう!

そこで以下のように実装しました

~plugin/nav-guard.js(実際のコードではありません)
export default ({app,redirect}) => {
    app.router.beforeEach(async (to,from,next)=>{
      if( /* 非認証ページ */ ) { 
        next();
      } else if( /* 別途ストアの中に認証用データがないとき */ ){
        redirect('/login');
      } else {
        const auth = await なんらかの非同期メソッド();
        if( /* なんらかの非同期メソッドがオッケーだった時 */ ){
          next();
        } else {
          redirect('/login');
        }
      }
    })
}

リダイレクト後のページのlayoutが遷移前のPageComponentのlayoutのママだったんですね。
Vue-devtoolで見てもlayoutそのまま。

これも、universalモードで、直接アクセスしたときにのみ発生してまして、その後CSRで遷移するときは問題ないのです。

対処法

  • redirect ではなく、routerの next でリダイレクトさせても発生
  • redirect ではなく、location.replace を使うと問題なし
  • redirect の時期を setTimeout すると時間によっては問題なし

2つ目は、layout/error を表示させてからリダイレクトする処理をしてた時に発見したんですが、早すぎてもだめでした。
ここも時間上の制約で深く探ってないです。
で、やっぱりredirectで処理させたかったので、\$nextTick ならどうだと思って、
API: コンテキスト - Nuxt.js
でどこからアクセスしようか探してた時に、nuxtState を発見しました。

こんな感じにすると無事正しいlayoutで表示されるようになりました。

~plugin/nav-guard.js(実際のコードではありません)
export default ({app,redirect,nuxtState}) => {
    app.router.beforeEach(async (to,from,next)=>{
      if( /* 非認証ページ */ ) { 
        next();
      } else if( /* 別途ストアの中に認証用データがないとき */ ){
        nuxtState.layout = 'login';
        redirect('/login');
      } else {
        const auth = await なんらかの非同期メソッド();
        if( /* なんらかの非同期メソッドがオッケーだった時 */ ){
          next();
        } else {
          nuxtState.layout = 'login';
          redirect('/login');
        }
      }
    })
}

(ただ、いまだに\$nextTickの実行方法がわかりません。app.\$nextTickは無いと怒られる...)

発生条件(がわかればいいなぁ)

これ、発生条件が自分には把握できず NuxtのGithubにもissue立ててないんですが、

  • nuxt バージョンは 1.4.2
  • universalモード
  • ナビゲーションガードはクライアントサイドのみ
  • コンポーネントが増えてくる前は大丈夫だった(ような気がする)
  • location.replace だと大丈夫

ぐらいしかわかってません。


ぶっちゃけ、全部middleware内で、SSRでもアクセス可能な形の認証にしたかった。
あと、next でやってないのOKなのかなって疑問。
時間ができたら再度nuxt側含めて探ってみる予定です。

7
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6