JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.2.26/vue.global.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/4.0.2/vuex.global.min.js"></script>
<div id="app">
<button :disabled="!prev" @click="fetchPokemons('prev')">prev</button>
<button :disabled="!next" @click="fetchPokemons('next')">next</button>
<div v-if="loading">loading...</div>
<div v-else>
<div v-for="n in pokemons" class="pokemon-list-item">{{ n.name }}</div>
</div>
</div>
CSS
.pokemon-list-item {
font-family: monospace;
margin: 10px;
padding: 10px;
border: 1px solid silver;
display: inline-block;
}
JavaScript
const store = Vuex.createStore({
state: {
pokemons: [],
next: 'https://pokeapi.co/api/v2/pokemon',
prev: null,
loading: false,
},
mutations: {
setLoading: (state, loading) => state.loading = loading,
setPokemons: (state, { pokemons, next, prev }) =>
Object.assign(state, { pokemons, next, prev }),
},
actions: {
async fetchPokemons({ state, commit }, page) {
if ([ 'next', 'prev' ].includes(page) && state[page] && !state.loading) {
commit('setLoading', true);
try {
const data = await fetch(state[page]).then(r => r.json());
commit('setPokemons', {
pokemons: data.results,
next: data.next,
prev: data.previous,
});
} catch (e) {
console.error(e);
}
commit('setLoading', false);
}
},
},
});
Vue.createApp({
computed: Vuex.mapState([ 'pokemons', 'prev', 'next', 'loading' ]),
methods: Vuex.mapActions([ 'fetchPokemons' ]),
created() {
this.fetchPokemons('next');
},
}).use(store).mount('#app');