Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] useAxios : Prevent request from firing immediately + add some options #992

Closed
damienroche opened this issue Dec 1, 2021 · 1 comment

Comments

@damienroche
Copy link
Contributor

damienroche commented Dec 1, 2021

With useFetch we have the ability to prevent the request from firing immediately.

This behavior was described in #449 but PR #499 finally doesn't include it.
However, for many use case we need to lazy the instance execution, while we need to access to other data from useAxios in template.

Considering this two following case :

users/index.vue

<template>
  <div v-if="isLoading">loading...</div>
  <div v-if="isFinished">
    <div v-for="user in users" :key="user.id">...</div>
    <button @click="increment">Next page</button>
    <button @click="dec">Previous page</button>
  </div>
</template>

<script lang="ts" setup>
import Users from '~/api/users'
import { get } from 'lodash'


const { execute, headers, isFinished, isLoading, data: users } = Users.index()
// Here, we don't know the last page number until we execute the request and get it on headers
const { count: page, inc, dec } = useCounter(1, { min: 0 })
const perPage = 20
const lastPage = ref(1)

const increment = () => {
  if (page.value < lastPage.value) {
    inc()
  }
}

whenever(headers, (h) => {
  lastPage.value = parseInt(get(h, 'x-pagination-total-pages', 1), 10)
})


watchEffect(() => {
  execute({ params: { page: page.value, perPage } })
}, { immediate: true })
</script>

users/create.vue

<template>
  <form @submit.prevent="onFormSubmit">
    <input type="email" v-model="email" />
    <input type="text" v-model="firstName" />
    <button>
      <span v-if="loading">creating...</span>
      <span v-if="!loading">Create user</span>
    </button>
  </form>
</template>

<script lang="ts" setup>
import Users from '~/api/users'

const email = ref('')
const firstName = ref('')

const { execute, loading } = Users.create()

onFormSubmit(() => {
  execute({ data: { email: email.value, firstName: firstName.value } })
})
</script>
api/users.ts

import instance from '~/api/client'
export default {
  index() {
    return useAxios(
      'users', 
      { 
        method: 'GET', 
        // We can pass some logic here, because it's not concerned by the view context
        params: { scope: 'registred' }
       },
      //  Pre-configured instance
       instance,
       {
         immediate: false,
       })
  },
  create() {
    return useAxios(
      'users',
      {
        method: 'POST'
      },
      instance,
      {
        immediate: false,
      }
    )
  }
}

api/client.ts

const DEFAULT_HEADERS = {
  'Content-Type': 'application/json',
  Accept: 'application/json',
}

const instance = axios.create({
  baseURL: import.meta.env.VITE_API_URL as string,
  headers: {
    ...DEFAULT_HEADERS,
  },
})

const requestHandler = (request) => {}

const responseHandler = (response) => {}

const errorHandler = (error) => {}

instance.interceptors.request.use(
  (request) => requestHandler(request),
  (error) => errorHandler(error)
)

instance.interceptors.response.use(
  (response) => responseHandler(response),
  (error) => errorHandler(error)
)

export default instance

In addition, I suggest to directly returns headers and maybe add another option in UseAxiosOptions in order to auto-convert data like axios-case-converter do (to discuss...)

First I suggest to introduce a UseAxiosOptions type optional parameter :

interface UseAxiosOptions {
   immediate: boolean
}
export interface UseAxiosReturn<T> {
   ...
   headers: Ref<T | undefined>
   execute: (config?: AxiosRequestConfig) => void
}

export function useAxios<T = any>(
  url: string,
  config: AxiosRequestConfig,
  instance: AxiosInstance,
  options?: UseAxiosOptions
): UseAxiosReturn<T>
unknownzjc added a commit to unknownzjc/vueuse that referenced this issue Jan 23, 2022
unknownzjc added a commit to unknownzjc/vueuse that referenced this issue Jan 23, 2022
@FRSgit
Copy link
Contributor

FRSgit commented Jun 27, 2022

@antfu I think this one can be closed as it's handled by #1170.

There was second thing suggested by @damienroche:

In addition, I suggest to directly returns headers and maybe add another option in UseAxiosOptions in order to auto-convert data like axios-case-converter do (to discuss...)

But I think this topic can be handled in a separate issue if needed

@wheatjs wheatjs closed this as completed Jan 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants