はじめに
axiosでAPIを叩いてエラーが返った時に、どの画面でも共通のエラーモーダルを表示したいと思い実装してみました。
Vuexでモーダルの状態を管理
モーダルの状態を管理するためのストアを用意します。
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について詳しく知りたい方はこちらを参照ください。
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に設定しておきましょう。
// 一部抜粋
plugins: ["~/plugins/axios"]
componentからモーダルを呼び出したい〜って時は以下のように呼び出せます。 (mapActionsヘルパーを使っても良いです)
$store.dispatch('error_modal/openErrorModal', { message: 'hoge' })
エラーモーダルコンポーネントをlayoutに配置
最後に作ったコンポーネントを配置して終わりです。
今回はlayouts/defaultに配置することでどのページからもエラーモーダルが必要な時に表示されるようにしました。設置箇所も一箇所でいいですしね。
<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を設置するのが、綺麗に纏まっていいなと思いました。
他にも色々実装方法があると思いますが、一例として参考になれば幸いです。
最後まで読んでいただきありがとうございました。