Search code examples
vue.jsvuexapollo-clientnativescript-vuevue-apollo

Why can't apollo get data in first request?


I am using props to get the Id of birds.

When I first start the app and click to enter the second-page, data won't load. It gives the following error;

JS: [Vue warn]: Error in render: "TypeError: Cannot read property 'name' of undefined"
JS:
JS: found in
JS:
JS: ---> <Detail> at components/Detail.vue
JS:        <Frame>
JS:          <Root>

But after I click on button second time it loads properly.


I have created a repo showing the problem. Please check it here: github repo

Working graphql playground

<template>
  <Page>
    <StackLayout>
      <Label :text="bird.name" textWrap="true" />
      <Button text="get data" @tap="getData" />
    </StackLayout>
  </Page>
</template>

<script>
import { gql } from "apollo-boost";

export default {
  props: ["birdID"],

  apollo: {
    bird: {
      query: gql`
        query($id: ID!) {
          bird(id: $id) {
            id
            name
          }
        }
      `,
      variables() {
        return {
          id: this.birdID,
        };
      },
    },
  },
  methods: {
    getData() {
      console.log("bird data: ", this.bird);
    },
  },
  mounted() {},
};
</script>

<style></style>

Is there a better way to get data?


Answer was correct

I have updated github repo with solution.

https://github.com/kaanguru/query-data-from-prop


Solution

  • The issue is that your template

    <Label :text="bird.name" textWrap="true" />
    

    attempts to display bird.name before your query has completed.

    The Vue Apollo documentation shows a simple work-around by defining some initial defaults

    You can initialize the property in your vue component's data hook

    data: () => ({
      bird: {
        name: null
      }
    }),
    

    Alternately, make use of the Loading state feature to conditionally render your components

    <Label v-if="$apollo.loading" text="loading" textWrap="true" />
    <StackLayout v-else>
      <Label :text="bird.name" textWrap="true" />
      <Button text="get data" @tap="getData" />
    </StackLayout>