'How to access a injected repository from a component's method
Lets say we injected this repository on a plugin/service-container.js
import nodeFetch from 'node-fetch'
import { AbortController as NodeAbortController } from 'node-abort-controller'
import HttpClient from '@/services/httpClient'
import PostRepository from '@/repositories/posts'
export default ({ app }, inject) => {
if (!process.client || app.context.env.NUXTJS_DEPLOY_TARGET === 'server') {
inject('postRepository', postRepository)
}
}
I have always acceded to API repositories from the asyncData method, like so:
export default {
async asyncData ({ $postRepository, }) {
const posts = await $postRepository.getAllPaginated(page, 11)
return {
posts,
}
}
}
But I need to access to it in a method, this is actually working but:
- I doesn't look the right way because i'm caching in the component's data()
- It fires this lint error:
Async method 'asyncData' has no 'await' expression.eslintrequire-await
What's the right way? I Can't find it online (the only examples I found involved using the Store)
export default {
async asyncData ({ $postRepository }) {
this.$postRepository = $postRepository
},
methods: {
async loadMore () {
if (this.page < this.posts.numPages) {
const posts = await this.$postRepository.getAllPaginated(this.page + 1, 11)
}
}
}
}
Solution 1:[1]
It seems that an injected dependency can be accessed (in this case) with simply this.$postRepository
inside any method so I didn't even need that asyncData
Solution 2:[2]
The error is coming from here
async asyncData ({ $postRepository }) {
this.$postRepository = [missing await here] $postRepository
},
From the documentation
This hook can only be used for page-level components. Unlike fetch, asyncData cannot access the component instance (this). Instead, it receives the context as its argument. You can use it to fetch some data and Nuxt will automatically shallow merge the returned object with the component data.
Hence, you cannot use any kind of this.loadMore
in asyncData
because it doesn't have access to the instance yet. So, inject is indeed the proper way of doing things.
With a plugin like that
export default ({ _ }, inject) => {
inject('customTest', async () => {
const response = await fetch('https://jsonplaceholder.typicode.com/todos/1')
return await response.json()
})
}
And a page like this
<template>
<div>
<pre>item: {{ item }}</pre>
</div>
</template>
<script>
export default {
async asyncData({ $customTest }) {
const item = await $customTest()
return { item }
},
}
</script>
It is not calling a method but you could totally use this.$nuxt.refresh()
to fetch it again and increment the index of the repository call after an update in the store.
Which could be referenced like
await fetch(`https://jsonplaceholder.typicode.com/todos/${indexFromVuex}`)
You could of course keep it local too
<template>
<div>
<pre>item: {{ item }}</pre>
<button @click="fetchNewItem">fetch new item</button>
</div>
</template>
<script>
export default {
async asyncData({ $customTest }) {
const item = await $customTest()
return { item }
},
data() {
return {
index: 1,
}
},
methods: {
async fetchNewItem() {
this.index += 1
this.item = await this.$customTest(this.index)
},
},
}
</script>
So yeah, I don't think that there are other possible approaches with asyncData
.
The fetch()
hook is a bit more flexible but it's also totally different too regarding how it is working.
Anyway, with those 2 approaches you could totally have enough to solve the issue of your HTTP call.
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 | kissu |