ловушка получения данных vue3

У меня есть собственный крючок для получения данных, которые выглядят следующим образом:

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
  };
}

Я пытаюсь использовать это в моем пользовательском компоненте, но я продолжаю получать эти данные undefined, хотя я могу видеть данные, если я выполняю console.log () в моем пользовательском хуке, где я вызываю конечную точку и регистрирую ответ .. .

Я пытаюсь использовать это так

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
    };
  }

Что я здесь делаю не так? В ловушке response.data содержит данные из файла JSON, но при вызове данных из ловушки в моем компоненте он равен нулю?


person envy    schedule 08.03.2021    source источник
comment
Я думаю, вам нужно await fetchData() в вашем компоненте, видя, что это асинхронная функция.   -  person Beyers    schedule 08.03.2021


Ответы (1)


В компонуемой функции постарайтесь не распространять состояние, поскольку оно теряет свою реактивность, вы можете использовать toRefs, чтобы вернуть реактивную ссылку:

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

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

затем в вызове компонента эта составная функция вне функции getCampaignData, например:

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)
    };
  }
person Boussadjra Brahim    schedule 08.03.2021
comment
спасибо, я обновил свой пример, но не могу заставить его работать, так как функция toRefs () жалуется на состояние в любом, даже если оно уже набрано? Если я напрямую ввожу toRefs () так: toRefs (state: State) - я получаю ошибку синтаксического анализа. - person envy; 08.03.2021
comment
пожалуйста, попробуйте return{... toRefs(state),fetchData} - person Boussadjra Brahim; 08.03.2021
comment
Аааа, да, это работает ... Однако, чтобы получить данные в компоненте, теперь мне нужно сделать: data.value.something для получения данных .... Разве нельзя избежать наличия .value на объект и просто получить данные как есть? например, мои данные существуют в свойстве данных ... теперь мне кажется, что я должен: data.value.data, а не просто data.data? - person envy; 08.03.2021
comment
Нет, так как toRefs преобразует состояние в ref, к которому следует обращаться с помощью свойства value. - person Boussadjra Brahim; 08.03.2021