'How to use Axios with Vue 3 Composition API

I am attempting to build a Pokemon filtered search app with Vue 3 and Composition API based on the following tutorial: https://www.youtube.com/watch?v=QJhqr7jqxVo. (GitHub: https://github.com/ErikCH/PokemonVue)

The fetch method used in the search component includes a reduce() function to handle urlIdLookup based on a specific id assigned to each Pokemon in the API response:

    const state = reactive({
      pokemons: [],
      filteredPokemon: computed(()=> updatePokemon()), 
      text: "",
      urlIdLookup: {}
      
    });

    fetch("https://pokeapi.co/api/v2/pokemon?offset=0")
      .then((res) => res.json())
      .then((data) => {
        console.log(data);
        state.pokemons = data.results;
        state.urlIdLookup = data.results.reduce((acc, cur, idx)=> 
           acc = {...acc, [cur.name]:idx+1 }
        ,{})
        console.log('url',state.urlIdLookup+1)
        
      });

urlIdLookup is then passed into the route used to display selected Pokemon info:

    <div
      class="ml-4 text-2xl text-blue-400"
      v-for="(pokemon, idx) in filteredPokemon"
      :key="idx"
    >
      <router-link :to="`/about/${urlIdLookup[pokemon.name]}`">
        {{ pokemon.name }}
      </router-link>
    </div>

Instead of using the above fetch setup, I wish to use Axios to handle the request and response from the Pokemon API. After installing Axios in the project and importing it into the component, I added a new fetchPokemon method:

    const fetchPokemon = () => {
      axios.get('https://pokeapi.co/api/v2/pokemon?offset=0')
      .then(response => {
        state.pokemons = response.data
      })
    }

    onMounted(() => {
      fetchPokemon()
    })

While using Axios in this new fetch method, I want to handle urlIdLookup similar to the previous fetch setup, but without using the reduce() method and de-structured accumulator, if possible. How can I go about using Axios to retrieve the urlId of each Pokemon, then pass that urlId into the "about" route in the template?

Here is the full component:

<template>
<div class="w-full flex justify-center">
<input placeholder="Enter Pokemon here" type="text" 
    class="mt-10 p-2 border-blue-500 border-2" v-model="text" />

</div>

  <div class="mt-10 p-4 flex flex-wrap justify-center">

    
    <div
      class="ml-4 text-2xl text-blue-400"
      v-for="(pokemon, idx) in filteredPokemon"
      :key="idx"
    >
      <router-link :to="`/about/${urlIdLookup[pokemon.name]}`">
        {{ pokemon.name }}
      </router-link>
    </div>
  </div>
</template>

<script>
import axios from 'axios';
import { reactive, toRefs, computed, onMounted } from "vue";
export default {
  setup() {
    const state = reactive({
      pokemons: [],
      filteredPokemon: computed(()=> updatePokemon()), 
      text: "",
      urlIdLookup: {}
      
    });

    const fetchPokemon = () => {
      axios.get('https://pokeapi.co/api/v2/pokemon?offset=0')
      .then(response => {
        state.pokemons = response.data
      })
    }

    onMounted(() => {
      fetchPokemon()
    })

    // fetch("https://pokeapi.co/api/v2/pokemon?offset=0")
    //   .then((res) => res.json())
    //   .then((data) => {
    //     console.log(data);
    //     state.pokemons = data.results;
    //     state.urlIdLookup = data.results.reduce((acc, cur, idx)=> 
    //        acc = {...acc, [cur.name]:idx+1 }
    //     ,{})
    //     console.log('url',state.urlIdLookup+1)
        
    //   });

    function updatePokemon(){
      if(!state.text){
        return [] 
      }
      return state.pokemons.filter((pokemon)=> 
          pokemon.name.includes(state.text)
      )
    }

    return { ...toRefs(state), fetchPokemon, updatePokemon };
  }
};
</script>



Solution 1:[1]

If I understood you correctly take a look at following snippet:

const { reactive, toRefs, computed, onMounted } = Vue
const { axioss } = axios
const app = Vue.createApp({
  setup() {
    const state = reactive({
      pokemons: [],
      filteredPokemon: computed(() => updatePokemon()),
      text: "",
      urlIdLookup: {},
    });

    const fetchPokemon = () => {
      axios
        .get("https://pokeapi.co/api/v2/pokemon?offset=0")
        .then((response) => {
          state.pokemons = response.data.results; // ? get just results
        });
    };

    fetchPokemon();
  
    // ? function to get index
    const getPokemonId = (item) => {
      return state.pokemons.findIndex((p) => p.name === item);
    };

    function updatePokemon() {
      if (!state.text) {
        return [];
      }
      return state.pokemons.filter((pokemon) =>
        pokemon.name.includes(state.text)
      );
    }
                                                        // ? return new function
    return { ...toRefs(state), fetchPokemon, updatePokemon, getPokemonId };
  },
})
app.mount('#demo')
<script src="https://unpkg.com/[email protected]/dist/vue.global.prod.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.26.1/axios.min.js" integrity="sha512-bPh3uwgU5qEMipS/VOmRqynnMXGGSRv+72H/N260MQeXZIK4PG48401Bsby9Nq5P5fz7hy5UGNmC/W1Z51h2GQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<div id="demo">
  <div class="w-full flex justify-center">
    <input
      placeholder="Enter Pokemon here"
      type="text"
      class="mt-10 p-2 border-blue-500 border-2"
      v-model="text"
    />
  </div>
  <div class="mt-10 p-4 flex flex-wrap justify-center">
    <div
      class="ml-4 text-2xl text-blue-400"
      v-for="(pokemon, i) in filteredPokemon"
      :key="i"
    >
                          <!-- // ? call function to get index -->
      <router-link :to="`/about/${getPokemonId(pokemon.name)}`">
        {{ pokemon.name }} - id {{ getPokemonId(pokemon.name) }}
      </router-link>
    </div>
  </div>
</div>

Solution 2:[2]

it seem id is not necessary, why not use name be id. if you want use interger be must, you can foreach results set index be id to each item, then

 <router-link :to="`/about/${pokemon.id}`">
        {{ pokemon.name }}
      </router-link>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 chen chen