I am using vue apollo inside Laravel. I followed the official documentation. Fetching data according to this:
https://vue-apollo.netlify.com/guide/apollo/#apollo is perfectly fine.
I wanted to use the apollo components to fetch the data.
So my Home.vue component looks like this:
<div>
<ApolloQuery :query="require('../graphql/queries/categories.gql')">
<template slot-scope="{ result: { data, loading } }">
<div v-if="loading">Loading...</div>
<ul v-else>
<li
v-for="category of data.categories"
class="user"
:key="category.id"
>{{ category.name }}</li>
</ul>
</template>
</ApolloQuery>
</div>
My categories.gql file looks like this:
query {
categories {
id
name
}
}
But while running yarn dev / watch i get the following error:
RROR in ./resources/js/graphql/queries/categories.graphql 1:6
Module parse failed: Unexpected token (1:6)
You may need an appropriate loader to handle this file type.
> query {
| categories {
| id
@ ./resources/js/components/Home.vue?vue&type=template&id=f2b6376c& (./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/Home.vue?vue&type=template&id=f2b6376c&) 9:24-72
You need to tell your bundle (for ex. Webpack) how to handle .gql files. Alternatively, you can do this in a JS file:
// queries/categories.js
import gql from 'graphql-tag'
export default gql`
query {
categories {
id
name
}
}
`
The things are not working as per the documentation. The official documentation needs to be updated.
@Akryum can you clarify your answer or please give some insights how to tell my webpack to handle it ? I am using laravel mix.
Install graphql-tag (as devDependencies) and then add this loader to your webpack configuration:
{
test: /\.(graphql|gql)$/,
exclude: /node_modules/,
loader: 'graphql-tag/loader'
}
If you google it, you'll find the complete graphql-tag documentation here.
I just realized I made a typo in the example I gave you earlier, it's graphql-tag not gql-tag. Sorry!
I followed your steps trying to solve this:
graphql/querirs/categories.js:
import gql from 'graphql-tag';
export default gql`
query {
categories {
id
name
}
}
`;
and my component:
<div>
<ApolloQuery :query="require('../graphql/queries/categories.js')">
<template slot-scope="{ result: { data, loading } }">
<div v-if="loading">Loading...</div>
<ul v-else>
<li
v-for="category of data.categories"
class="user"
:key="category.id"
>{{ category.name }}</li>
</ul>
</template>
</ApolloQuery>
</div>
I am getting following error on my console:
Vue warn]: Invalid prop: type check failed for prop "query". Expected Object, got Module
found in
---> <ApolloQuery>
<Home> at resources/js/components/Home.vue
<Root>
Did i followed your steps correctly ? Correct me if I am wrong.
Since you are now exporting a module, you need to take the default export in the require:
require('../graphql/queries/categories.js').default
You can also write this query in the component:
<template>
<ApolloQuery :query="$options.queries.categories">...</ApolloQuery>
</template>
<script>
import gql from 'graphql-tag'
export default {
queries: {
categories: gql`
query {
categories {
id
name
}
}
`,
},
}
</script>
This is the approach I recently started using since it better co-locates the data requirements of the component with itself. I'll update the docs in the future.
I added a loader to my webpack.mix.js file:
mix.webpackConfig({
module: {
rules: [
{
test: /\.(graphql|gql)$/,
exclude: /node_modules/,
loader: 'graphql-tag/loader'
}
]
}
});
Now I am able to get the data from graphql server and the categories list is also displayed in the list. But still I am getting error in console.
My home.vue:
<template>
<div>
<ApolloQuery :query="require('../graphql/queries/categories.gql')">
<template slot-scope="{ result: { data, loading } }">
<div v-if="loading">Loading...</div>
<ul v-else>
<li v-for="category of data.categories" :key="category.id">{{ category.name }}</li>
</ul>
</template>
</ApolloQuery>
</div>
</template>
Error on console:
app.js:49922 [Vue warn]: Error in render: "TypeError: Cannot read property 'categories' of null"
found in
---> <ApolloQuery>
<Home> at resources/js/components/Home.vue
<Root>
warn @ app.js:49922
logError @ app.js:51147
globalHandleError @ app.js:51142
handleError @ app.js:51131
Vue._render @ app.js:53967
updateComponent @ app.js:52218
get @ app.js:52588
Watcher @ app.js:52577
mountComponent @ app.js:52225
./node_modules/vue/dist/vue.common.js.Vue.$mount @ app.js:57949
./node_modules/vue/dist/vue.common.js.Vue.$mount @ app.js:60362
init @ app.js:53554
createComponent @ app.js:55000
createElm @ app.js:54947
createChildren @ app.js:55075
createElm @ app.js:54976
patch @ app.js:55499
Vue._update @ app.js:52097
updateComponent @ app.js:52218
get @ app.js:52588
Watcher @ app.js:52577
mountComponent @ app.js:52225
./node_modules/vue/dist/vue.common.js.Vue.$mount @ app.js:57949
./node_modules/vue/dist/vue.common.js.Vue.$mount @ app.js:60362
init @ app.js:53554
createComponent @ app.js:55000
createElm @ app.js:54947
createChildren @ app.js:55075
createElm @ app.js:54976
patch @ app.js:55538
Vue._update @ app.js:52097
updateComponent @ app.js:52218
get @ app.js:52588
Watcher @ app.js:52577
mountComponent @ app.js:52225
./node_modules/vue/dist/vue.common.js.Vue.$mount @ app.js:57949
./node_modules/vue/dist/vue.common.js.Vue.$mount @ app.js:60362
Vue._init @ app.js:54055
Vue @ app.js:54122
./resources/js/app.js @ app.js:61211
__webpack_require__ @ app.js:20
0 @ app.js:61539
__webpack_require__ @ app.js:20
(anonymous) @ app.js:84
(anonymous) @ app.js:87
app.js:51151 TypeError: Cannot read property 'categories' of null
at Object.fn [as default] (app.js:46542)
at Proxy.render (app.js:46135)
at VueComponent.Vue._render (app.js:53965)
at VueComponent.updateComponent (app.js:52218)
at Watcher.get (app.js:52588)
at new Watcher (app.js:52577)
at mountComponent (app.js:52225)
at VueComponent../node_modules/vue/dist/vue.common.js.Vue.$mount (app.js:57949)
at VueComponent../node_modules/vue/dist/vue.common.js.Vue.$mount (app.js:60362)
at init (app.js:53554)
Try chaging v-else to v-else-if="data"
I did fix it by
<template slot-scope="{ result: { data, loading }, isLoading }">
<div v-if="isLoading">Loading...</div>
Which displays loading message when the data is loading.
@Akryum many thanks. Closing the issue.
Most helpful comment
Since you are now exporting a module, you need to take the default export in the
require:You can also write this query in the component:
This is the approach I recently started using since it better co-locates the data requirements of the component with itself. I'll update the docs in the future.