Vue-apollo: Facing issues with Laravel : You may need an appropriate loader to handle this file type.

Created on 23 Jan 2019  路  11Comments  路  Source: vuejs/vue-apollo

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

Most helpful comment

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.

All 11 comments

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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

seanaye picture seanaye  路  3Comments

sadhakbj picture sadhakbj  路  3Comments

dsbert picture dsbert  路  4Comments

jsrkstr picture jsrkstr  路  3Comments

apertureless picture apertureless  路  4Comments