pinia icon indicating copy to clipboard operation
pinia copied to clipboard

Implement nuxtServerInit Action to load data from server-side on the initial load

Open MarceloLuis1997 opened this issue 2 years ago • 8 comments

What problem is this solving

Implement something like NuxtServerInit Action, so we can load data from the server-side and give it directly to the client-side on the initial load/render.

Proposed solution

Include an index.js file inside /stores with a nuxtServerInit action which will be called from the server-side on the initial load.

Describe alternatives you've considered

The only way I found to do this is using Pinia with Vuex, using the nuxtServerInit from Vuex:

// store/index.js
import { useSessionStore } from '~/stores/session'

export const actions = {
  async nuxtServerInit ({ dispatch }, { req, redirect, $pinia }) {
    if (!req.url.includes('/auth/')) {
      const store = useSessionStore($pinia)

      try {
        await store.me() // load user information from the server-side before rendering on client-side
      } catch (e) {
        redirect('/auth/login') // redirects to login if user is not logged in
      }
    }
  }
}

MarceloLuis1997 avatar Feb 18 '22 13:02 MarceloLuis1997

#947

MarceloLuis1997 avatar Feb 18 '22 20:02 MarceloLuis1997

There should be a way to add this for both setup and option stores. Maybe a specific name for an action is enough.

One important thing to note is that given the nature of stores in pinia, you need explicitly say somewhere in your server code which stores must run this action as they need to be instantiated on the server. By default, if no store is ever user, no store is ever instantiated and therefore no server init function can run.

posva avatar Feb 22 '22 12:02 posva

What problem is this solving

Implement something like NuxtServerInit Action, so we can load data from the server-side and give it directly to the client-side on the initial load/render.

Proposed solution

Include an index.js file inside /stores with a nuxtServerInit action which will be called from the server-side on the initial load.

Describe alternatives you've considered

The only way I found to do this is using Pinia with Vuex, using the nuxtServerInit from Vuex:

// store/index.js
import { useSessionStore } from '~/stores/session'

export const actions = {
  async nuxtServerInit ({ dispatch }, { req, redirect, $pinia }) {
    if (!req.url.includes('/auth/')) {
      const store = useSessionStore($pinia)

      try {
        await store.me() // load user information from the server-side before rendering on client-side
      } catch (e) {
        redirect('/auth/login') // redirects to login if user is not logged in
      }
    }
  }
}

Thanks for this workaround, I would also love to see the feature implemented

AustinMusiku avatar Jun 01 '22 21:06 AustinMusiku

What problem is this solving

Implement something like NuxtServerInit Action, so we can load data from the server-side and give it directly to the client-side on the initial load/render.

Proposed solution

Include an index.js file inside /stores with a nuxtServerInit action which will be called from the server-side on the initial load.

Describe alternatives you've considered

The only way I found to do this is using Pinia with Vuex, using the nuxtServerInit from Vuex:

// store/index.js
import { useSessionStore } from '~/stores/session'

export const actions = {
  async nuxtServerInit ({ dispatch }, { req, redirect, $pinia }) {
    if (!req.url.includes('/auth/')) {
      const store = useSessionStore($pinia)

      try {
        await store.me() // load user information from the server-side before rendering on client-side
      } catch (e) {
        redirect('/auth/login') // redirects to login if user is not logged in
      }
    }
  }
}

Thanks for this workaround, I would also love to see the feature implemented

Did the stores are shared?

matifanger avatar Jun 14 '22 17:06 matifanger

This solution is workaround for me:

nuxt.config.ts

plugins: [
   { src: '~/plugins/init.server.ts' }, // must be the first server plugin
 ]

plugins/init.server.ts

import { useGlobalStateStore } from '~/store/globalState';

const initServer: () => void = async () => {
    // example code
    const host = req.hostname;
    const globalStateStore = useGlobalStateStore();
    globalStateStore.SET_HOST({ host });
};

export default initServer;

nestle49 avatar Aug 22 '22 12:08 nestle49

@nestle49 Can this be placed as a nitro plugin in a nuxt project instead?

MuhammadM1998 avatar Dec 11 '22 21:12 MuhammadM1998

Any update on this ?

mrleblanc101 avatar Jul 11 '23 22:07 mrleblanc101

It looks like currently, we can't use a store with inject() call inside, from the nuxt plugin.

inject() call simply throws the following error.

[Vue warn]: inject() can only be used inside setup() or functional components.

Tested with Nuxt/Bridge btw.

yshrsmz avatar Dec 02 '23 16:12 yshrsmz