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

Whether using useAxios within a function fails to track responsive data #3981

Closed
7 tasks done
sunpm opened this issue May 19, 2024 · 10 comments
Closed
7 tasks done

Whether using useAxios within a function fails to track responsive data #3981

sunpm opened this issue May 19, 2024 · 10 comments

Comments

@sunpm
Copy link

sunpm commented May 19, 2024

Describe the bug

<script setup lang="ts">
const loading = ref(false)

function getData() {
	const { data, isLoading, isFinished, execute, abort, isAborted } = useAxios(
	  'https://jsonplaceholder.typicode.com/todos/1',
	)
	loading.value = isLoading.value // true
}

getData()
</script>

loading cannot be changed to false after the request is completed.

I'm sure it's not a vueuse problem, but rather that vue is designed that way, but I don't know how to fix it

This is currently possible, but I'd like to know if there are any other more elegant ways to write it.

<script setup lang="ts">
const loading = ref(false)

function getData() {
	const { data, isLoading, isFinished, execute, abort, isAborted } = useAxios(
	  'https://jsonplaceholder.typicode.com/todos/1',
	)
	watchEffect(() => {
	  loading.value = isLoading.value
	})
}

getData()

Reproduction

https://github.com/vueuse/vueuse/blob/main/packages/integrations/useAxios/demo.vue

System Info

System:
    OS: macOS 12.6.5
    CPU: (4) x64 Intel(R) Core(TM) i5-6500 CPU @ 3.20GHz
    Memory: 31.03 MB / 32.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 18.17.1 - ~/.nvm/versions/node/v18.17.1/bin/node
    Yarn: 1.22.17 - /usr/local/bin/yarn
    npm: 9.6.7 - ~/.nvm/versions/node/v18.17.1/bin/npm
  Browsers:
    Chrome: 124.0.6367.208
    Firefox: 63.0.3
  npmPackages:
    @vueuse/core: ^10.9.0 => 10.9.0 
    @vueuse/integrations: ^10.9.0 => 10.9.0 
    vue: ^3.4.27 => 3.4.27

Used Package Manager

pnpm

Validations

@VividLemon
Copy link
Contributor

VividLemon commented May 22, 2024

That code is working for me

const loading = ref(false)

function getData() {
  const { data, isLoading, isFinished, execute, abort, isAborted } = useAxios(
    'https://jsonplaceholder.typicode.com/todos/1',
  )
  watchEffect(() => {
    loading.value = isLoading.value
  })
  return { execute, data }
}

const a = getData()

setTimeout(() => {
  a.execute()
}, 1500)

getData becomes itself a new composable. With composable rules. However, you probably want to move useAxios out of the getData function and expose it as root in the setup function

In terms of "loading". I'd probably do

const {isLoading} = useAxios()

const _loading = ref(false)
const loading = computed(() => isLoading.value || _loading.value)

But that's even assuming _loading needs to exist. Hypothetically if you needed to use it somewhere else, but tracking the loading elements individually is probably best

const loading = ref(false)
const {isLoading, data, execute} = useAxios() // This doesn't need to be defined in a function
// You're going to be rebuilding useAxios on each function call. So you'd have new returned refs from useAxios.
// This isn't "bad", it's actually just a new composable at this point

@sunpm
Copy link
Author

sunpm commented May 23, 2024

该代码对我有用

const loading = ref(false)

function getData() {
  const { data, isLoading, isFinished, execute, abort, isAborted } = useAxios(
    'https://jsonplaceholder.typicode.com/todos/1',
  )
  watchEffect(() => {
    loading.value = isLoading.value
  })
  return { execute, data }
}

const a = getData()

setTimeout(() => {
  a.execute()
}, 1500)

getData本身成为一个新的可组合项。使用可组合规则。但是,您可能希望将 useAxios 移出 getData 函数,并在 setup 函数中将其作为 root 公开

就“加载”而言。我可能会这样做

const {isLoading} = useAxios()

const _loading = ref(false)
const loading = computed(() => isLoading.value || _loading.value)

但这甚至假设 _loading 需要存在。假设您需要在其他地方使用它,但单独跟踪加载元素可能是最好的

const loading = ref(false)
const {isLoading, data, execute} = useAxios() // This doesn't need to be defined in a function
// You're going to be rebuilding useAxios on each function call. So you'd have new returned refs from useAxios.
// This isn't "bad", it's actually just a new composable at this point

If useAxios is placed inside a function, you can only use wtchEffect to listen for changes before assigning them to an external ref right?

@VividLemon
Copy link
Contributor

I dont understand the question

@sunpm
Copy link
Author

sunpm commented May 23, 2024

This is how I currently write it, the responsive data is placed in watchEffect which responds correctly

<script setup lang="ts">
const loading = ref(false)
const list = ref([])

function getData() {
	const { data, isLoading } = useAxios(
	  'https://jsonplaceholder.typicode.com/todos/1',
	)
	watchEffect(() => {
	  loading.value = isLoading.value
	  list.value = data.value
	})
}

getData()
</script>

<template>
  <el-table
    v-loading="loading"
    :data="list"
    style="width: 100%">
    <el-table-column
      prop="date"
      label="日期"
      width="180">
    </el-table-column>
    <el-table-column
      prop="name"
      label="姓名"
      width="180">
    </el-table-column>
    <el-table-column
      prop="address"
      label="地址">
    </el-table-column>
  </el-table>
</template>

@VividLemon
Copy link
Contributor

You can just rewrite to this. You dont need the wrapping composable function

const { data: list, isLoading: loading, execute } = useAxios('https://jsonplaceholder.typicode.com/todos/1') 	

@sunpm
Copy link
Author

sunpm commented May 23, 2024

您可以直接重写此内容。您不需要包装可组合函数

const { data: list, isLoading: loading, execute } = useAxios('https://jsonplaceholder.typicode.com/todos/1') 	

This way the component loading will request the interface, how can I implement this if I need event triggering? I'm sorry, maybe my question is low-level

@VividLemon
Copy link
Contributor

I dont understand the question, but the execute function re-fetches the data

@sunpm
Copy link
Author

sunpm commented May 23, 2024

Written in this way, when entering this component or page, use Axios will be called immediately. If you don’t want to call it immediately, you can only use function packaging.

<script setup lang="ts">
const { data: list, isLoading: loading, execute } = useAxios('https://jsonplaceholder.typicode.com/todos/1') 	
</script>

@VividLemon
Copy link
Contributor

const { execute } = useAxios(url1, { method: 'GET' }, { immediate: false }) <- immediate: false

@sunpm
Copy link
Author

sunpm commented May 23, 2024

Thanks, my fault for not checking the docs carefully!

@sunpm sunpm closed this as completed May 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants