envy
envy

Reputation: 365

vue3 fetch data hook

I have a custom hook to fetch data that is looking like this:

import { reactive } from 'vue';
import axios from 'axios';

interface State {
  isLoading: boolean;
  isError: boolean;
  errorMessage: string,
  data: object|null
}

export default function useAxios(url: string, data: object) {
  const state = reactive({
    isLoading: true,
    isError: false,
    errorMessage: '',
    data: null
  }) as State;

  const fetchData = async () => {
    try {
      const response = await axios({
        method: 'GET',
        url: url, // '/test_data/campaign.json'
        data: data
      });
      state.data = response.data;
    } catch (e) {
      state.isError = true;
      state.errorMessage = e.message;
    } finally {
      state.isLoading = false;
    }
  };

  return {
    toRefs(state), //TS complains over "Parameter 'state' implicitly has an 'any' type." But it's already typed in the above???
    fetchData
  };
}

Im trying to use this in my custom component, but I keep getting that data is undefined, even though I can see the data if I do a console.log() in my custom hook where im calling the endpoint and logging the response...

Im trying to use it like this

setup() {
    const state = reactive({
      data: null
    });
    const {data, isLoading, fetchData} = useAxios(
      '/test_data/campaign.json',
      {}
    );
    const getCampaignData = async () => {
      await fetchData();
      console.log('data', data);
      state.data = data;
    };

    onMounted(() => {
      getCampaignData();
    });

    return {
      data: state.data
    };
  }

What am I doing wrong here? In the hook, response.data has the data from the JSON file, but when calling the data from the hook in my component, it's null ?

Upvotes: 2

Views: 3490

Answers (1)

Boussadjra Brahim
Boussadjra Brahim

Reputation: 1

In composable function try to not spread the state since it loses its reactivity, you could use toRefs to return a reactive ref :

import {reactive,toRefs} from 'vue';
import axios from 'axios';

export default function useAxios(url: string, data: object) {
....
  return {
    ...toRefs(state),
    fetchData
  }
}

then in your component call that composable function outside the getCampaignData function like :

import {reactive,toRefs,onMounted} from 'vue';
setup() {
    const state = reactive({
      data: null
    });
 const { data, isLoading, fetchData } = useAxios(
        '/test_data/campaign.json',
        {}
      );
    const getCampaignData = async () => {
     
      await fetchData();
      
      state.data = data.value;
    };

    onMounted( ()=>{
        getCampaignData();
    })

    return {
      ...toRefs(state)
    };
  }

Upvotes: 1

Related Questions