はじめに
サーバサイドの開発歴は1年程度で、最近初めて業務でフロントエンド開発を担うようになりました。
フロントエンド開発めちゃくちゃ楽しいです。
記事の目的
さて、JS のライブラリとして Vue.js を使っているのですが、 Vue-infinite-loading という無限スクロールを簡単にに実現できるライブラリがあります。
この無限スクロール機能では API を叩いて データを取得する処理が必要となります。これらの処理を状態管理のライブラリである Vuex で扱いたい、というのが本記事のモチベーションです。
ググってみたのですが、ドキュメントには記載がなく、 Issue にコードの一部が載っている程度でした。私はフロントエンド歴が浅いためか、 Issue だけではすぐに理解が出来ず、試行錯誤の末にやっとできましたので、コードの全体像を載せてみようと思います。
参考
実装例
ドキュメント例と同様に Hacker News の API を利用してニュース記事を取得する想定です。
実際に動かしたわけではないので、あくまでもイメージです。
ポイントは NOTE:
としてコメントで記載しております。
store.js
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex)
const api = '//hn.algolia.com/api/v1/search_by_date?tags=story';
const store = new Vuex.Store({
state: {
page: 1,
hits: []
}
mutations: {
incrementPage(state) {
state.page++
},
addHits(state, hits) {
state.hits.push(...hits)
}
}
actions: {
async fetchHits({commit, state}, loadState) {
const { data } = await axios.get(api, {
params: {
page: state.page
}
})
if (data.hits.length) {
commit('incrementPage')
commit('addHits', data.hits)
// NOTE: loadStateには $state が入っているので、loadState をレシーバとして、 loaded や complete を 呼び出すことで、読み込み状態の制御をできる
loadState.loadState.loaded()
} else {
loadState.loadState.complete()
}
}
}
})
export default store
application.vue
<template>
<div v-for="(hit, $index) in hits" :key="$index">
<!-- Hacker News item loop -->
</div>
<infinite-loading @infinite="infiniteHandler"></infinite-loading>
</template>
<script>
import { mapState, mapActions } from 'vuex'
export default {
computed: {
...mapState(['hits'])
},
methods: {
...mapActions(['fetchHits']),
// NOTE: $state を受け取るメソッドを定義し、ディスパッチ時にに引数として $state を渡す
infiniteHandler($state) {
this.fetchHits($state)
}
}
}
</script>
最後に
よりよい実装方法などありましたら、教えていただけると幸いです🙏
記事が参考になりましたら、「LGTM」お願いします🙏