No More Posting New Topics!

If you have a question or an issue, please start a thread in our Github Discussions Forum.
This forum is closed for new threads/ topics.

Navigation

    Quasar Framework

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search

    How to call "mounted" in ssr

    Help
    1
    1
    559
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • D
      dzzq last edited by

      According to the docs:

      https://quasar.dev/quasar-cli/developing-ssr/writing-universal-code#Component-Lifecycle-Hooks

      Since there are no dynamic updates, of all the Vue lifecycle hooks, only beforeCreate and created will be called during SSR. This means any code inside other lifecycle hooks such as beforeMount or mounted will only be executed on the client.

      I’m confused at how to make this call happen. I have some stuff that can’t run on the server. I would have guessed that having “mounted” alone would cause it to fire, but that doesn’t seem to happen.

      To add a little context, I’m building a drop-down menu using foundation. I have it working on standard Vue (non-ssr).

      The file looks like this:

      <template>
      
      <ul class="vertical menu accordion-menu" data-accordion-menu data-multi-open="false">
          <li v-for="i in htmlData.sidenav" :key="i.title">
              <router-link v-bind:to=i.href>{{ i.title }}</router-link>
              <ul class="menu vertical nested" v-if="i.sub1">
                  <li v-for="j in i.sub1" :key="j.name">
                      <router-link v-bind:to=j.href>{{ j.name }}</router-link>
                      <ul class="menu vertical nested" v-if="j.sub2">
                          <li v-for="k in j.sub2" :key="k.name">
                              <router-link v-bind:to=k.href>{{ k.name }}</router-link>
                            </li>
                        </ul>
                    </li>
                </ul>
            </li>
        </ul>
      </div>
      
      
      </template>
      
      
      <script>
      import SideNav from '../store/modules/sidenav'
      import $ from 'jquery'
      
      export default {
          name: 'sidenav',
      
          computed: {
              htmlData () {
                  this.acc()
                  return this.$store.state.sn.nav
              }
          },
      
          // Server-side only
          serverPrefetch () {
              this.$store.registerModule('sn',  SideNav)
              return this.getData()
          },
      
          // Client-side only
          mounted () {
              console.log('mt')
              const doesExist = !!this.$store.state.sn.nav
              this.$store.registerModule('sn', SideNav, { preserveState: true })
      
              if (!doesExist) {
                  this.getData()
              }
          },
      
          destroyed () {
              this.$store.unregisterModule('sn')
              this.menu.destroy()
          },
      
          methods: {
              async getData () {
                  return this.$store.dispatch('sn/snav')
              },
      
              acc () {
                  this.$nextTick(function () {
                      this.menu = new this.$foundation.AccordionMenu($('.accordion-menu'))
                  })
              },
          }
      }
      

      While the sidenav does render, the client is unable to see it, which results in this error:

      UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'AccordionMenu' of undefined
      

      This is wrong because the menu does render, there is no log of mt in console, although pref does log. This causes a slew of other problems with page rendering (it doesn’t without hard refresh).

      The file under boot/sidenav looks like this:

      // const SideNav = () => import('../layouts/SideNav.vue')
      import SideNav from '../layouts/SideNav.vue'
      
      export default async ({ Vue }) => {
          Vue.component('side-nav', SideNav)
      }
      
      

      And the quasar.conf has this:

              boot: [
                  'axios',
                  'sidenav',
                  'notemenu',
                  {
                      path: 'foundation',
                      server: false
                  },
                  {
                      path: 'osmd',
                      server: false
                  }
              ],
      
      

      The client can’t see either foundation or osmd. Neither can run on the server since they both require window to run. It’s doubly confusing because sidenav does render and behave like a reactive component.

      1 Reply Last reply Reply Quote 0
      • First post
        Last post