2

New to Nuxt and SSR. What I'm trying to do is straightforward: I'm trying to trigger a function before the page loads that will SSR my firestore data. If I add a button with @onclick, it works fine. But when I try to replace the Button/OnClick with @onloadstart or something similar, nothing happens.

What am I missing? I suspect I’m thinking about this through a client side lens. Not a SSR lens.

 <template @onloadstart="beforeCreate()">
  <section>
    <div>
      <div v-for="article in articles" id="articleCardList" :key="article">
        <v-card elevation="1" outlined>
          <div class="d-flex">
            <v-avatar class="ma-1" size="125" tile>
              <v-img :src="article.thumbnail"></v-img>
            </v-avatar>
            <div>
              <v-card-title
                class="text-h5 text-wrap d-flex justify-space-between text-caption"
                v-text="article.title"
              >
                {{ article.title }}
              </v-card-title>
            </div>
          </div>
        </v-card>
      </div>
    </div>
  </section>
</template>
<script>
import { fireDb } from '~/plugins/firebase.js'
export default {
  data() {
    return {
      articles: [],
    }
  },

  methods: {
    async asyncData() {
      this.articles = []

      await fireDb
        .collection('articles')
        .get()
        .then((querySnapShot) => {
          querySnapShot.forEach((doc) => {
            this.articles.push({
              id: doc.id,
              title: doc.data().title,
              description: doc.data().description,
              thumbnail: doc.data().thumbnail,
              date: doc.data().date,
              link: doc.data().link,
              source: doc.data().source,
            })
            console.log(this.articles)
          })
        })
    },
    beforeCreate() {
      window.addEventListener('beforeCreate', this.asyncData)
    },
  },
}
</script>
5
  • It's @click actually. Did you tried it? @clickis client side only tho. Commented Jun 2, 2021 at 22:09
  • Otherwise, using fetch() hook and managing a loading state could be nice while fetching the data from firebase. You could also use created()but this one will not block the rendering until it's done fetching. Actually, only asyncData does but it's just between a page transition hence, if you arrive on this page it will not be handled. Not sure but maybe a middleware could be blocking, need to try it out. Does your event listener work btw? Commented Jun 2, 2021 at 22:17
  • Yes, if I add a button with @click=“asyncData”, it works. But I don’t want to trigger data loading with a manual click. I want the data to load automatically on render. Commented Jun 2, 2021 at 22:18
  • No, the beforeCreate. Does it trigger something at all? Otherwise, I gave you the alternative (fetch()hook). Commented Jun 2, 2021 at 22:24
  • There is a helper for this btw: $fetchState.pending as stated in the docs: nuxtjs.org/docs/2.x/components-glossary/pages-fetch Commented Jun 2, 2021 at 22:58

1 Answer 1

2

You're close to a working solution in terms of having the component automatically fetch data before the page loads. Instead of beforeCreate, you'd use the asyncData hook (which seems to be your initial attempt).

The problem is you've declared asyncData as a component method, but it needs to be at the top level of the object definition for it to be used as a component hook.

export default {
  // ✅ declared as a hook
  asyncData() {...},

  methods: {
    // ❌ this should be at the top level
    asyncData() {...} 
  },
}

Be aware that asyncData can only be used in page or layout components. Otherwise, you need to switch to the fetch hook.

asyncData() has no access to this (as it's run before the page component), so those references should be removed. Instead, asyncData() should return an object of data similar to that returned from data() (i.e., { ​articles }):

export default {
  ​asyncData() {
    ​const articles = []

    ​await fireDb
      ​.collection('articles')
      ​.get()
      ​.then((querySnapShot) => {
        ​querySnapShot.forEach((doc) => {
          ​articles.push(/*...*/)
        ​})
      ​})

    console.log(articles)
    return { articles }
  }
}
Sign up to request clarification or add additional context in comments.

1 Comment

I noticed return articles inside forEach, which does not make sense. That return needs to be the last line of asyncData(), outside the forEach.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.