7
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Nuxt.js+Vuex+Bulmaで共通で使えるエラーモーダルを作る

Last updated at Posted at 2019-03-23

はじめに

axiosでAPIを叩いてエラーが返った時に、どの画面でも共通のエラーモーダルを表示したいと思い実装してみました。

Vuexでモーダルの状態を管理

モーダルの状態を管理するためのストアを用意します。

~/store/error_modal.js
export const state = () => ({
  message: '',
  isActive: false
})

export const mutations = {
  setMessage(state, message) {
    state.message = message
  },
  active(state) {
    state.isActive = true
  },
  deactive(state) {
    state.isActive = false
  }
}

export const actions = {
  openErrorModal({ commit }, payload) {
    commit('setMessage', payload.message)
    commit('active')
  },
  closeErrorModal({ commit }) {
    commit('deactive')
    commit('setMessage', '')
  }
}

モーダルのコンポーネントを作成

モーダルのコンポーネントを用意します。
Bulmaでtemplateを作っているので簡単にモーダルのデザインを作ることが出来ました。

また先ほど作ったerror_modalのstateとcloseErrorModalをそれぞれバインドします。
stateをバインドすることで、error_modalのisActiveがtrueに変更されるとモーダルが表示される寸法です。

あとはモーダルのバックグランドとクローズボタンにcloseErrorModal()をバインドしてあげてモーダルのクローズも完了です。

<template>
  <div class="modal" :class="{ 'is-active': this.isActive }">
    <div class="modal-background" @click="closeErrorModal" />
    <div class="modal-content">
      <div class="notification is-warning">
        <button class="delete" aria-label="close" @click="closeErrorModal" />
        {{ this.message }}
      </div>
    </div>
  </div>
</template>

<script>
import { mapState, mapActions } from 'vuex'

export default {
  computed: {
    ...mapState('error_modal', [
      'message',
      'isActive'
    ])
  },
  methods: {
    ...mapActions('error_modal', [
      'closeErrorModal'
    ])
  }
}
</script>

axiosのエラーハンドリング用pluginを作る

今回やりたかったのはaxiosでAPI通信をしてエラーが返ってきた時、モーダルを表示したかったので、axios用のpluginを作ってモーダル表示の処理を追加します。
axiosのInterceptorsについて詳しく知りたい方はこちらを参照ください。

plugins/axios.js
export default function({ $axios, store }) {
  $axios.onError(error => {
    if (error.response == null) { return }
    store.dispatch('error_modal/openErrorModal', { message: error.response.data.message })
  })
}

(ここではerror.responseがあったら単純にモーダル表示にしてますが、statusやcode_nameなどでよしなにハンドリングするのが良いと思います。)

作ったpluginは忘れずにnuxt.configに設定しておきましょう。

nuxt.config.js
  // 一部抜粋
  plugins: ["~/plugins/axios"]

componentからモーダルを呼び出したい〜って時は以下のように呼び出せます。 (mapActionsヘルパーを使っても良いです)

$store.dispatch('error_modal/openErrorModal', { message: 'hoge' })

エラーモーダルコンポーネントをlayoutに配置

最後に作ったコンポーネントを配置して終わりです。
今回はlayouts/defaultに配置することでどのページからもエラーモーダルが必要な時に表示されるようにしました。設置箇所も一箇所でいいですしね。

layouts/default.vue
<template>
  <div>
    <nuxt />
    <error-modal />
  </div>
</template>

<script>
import ErrorModal from '~/components/ErrorModal.vue'

export default {
  components: {
    ErrorModal
  }
}
</script>

まとめ

VuexとBulmaを使って少ないコードでエラーモーダルを表示することが出来ました。
使う側もコンポーネントをimportするだけなのでスッキリ。

今回は非同期処理でのエラーハンドリングに使いましたが、どの画面でも共通したモーダルなり、トーストなり出したい時にはVuexで状態管理して、共通のlayoutsでcomponentを設置するのが、綺麗に纏まっていいなと思いました。

他にも色々実装方法があると思いますが、一例として参考になれば幸いです。
最後まで読んでいただきありがとうございました。

7
7
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
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?