1

I have such a problem: I need to get localStorage data before nuxt layout is loaded in pages/index.vue

/pages/index.vue

<script>
export default {
  layout (context) {
    if (localStorage.getItem('AUTH_TOKEN')){
      this.$store.dispatch('changeAuthStatus', {
        authStatus: true,
        accessToken: localStorage.getItem('AUTH_TOKEN'),
        profileData: JSON.parse(localStorage.getItem('PROFILE_DATA'))
      }).then(() => {
        this.$store.dispatch('changeLoadedStatus', {
          isLoaded: true
        })
      })
    }
    else {
      this.$router.push('/auth')
    }
  }
</script>

The error when the page is loaded: localStorage is not defined

Maybe I can get localStorage data using context? Or maybe you can suggest to me any package so I can use it in the layout function?

6
  • Btw, you're using layout here? nuxtjs.org/docs/2.x/components-glossary/pages-layout Didn't you mean middleware()? nuxtjs.org/docs/2.x/components-glossary/… Commented Aug 4, 2021 at 15:30
  • Yes, I use layout, I need to get the profileData from localStorage to choose what layout will be loaded next Commented Aug 4, 2021 at 15:31
  • Also, prefer using the async/await syntax rather than .then. It's usually recommended. Commented Aug 4, 2021 at 15:43
  • 1
    I don't know if it helps you or not, but I mostly use universal storage for setting and retrieving tokens, using the $storage.setUniversal() and $storage.getUniversal() methods. github.com/nuxt-community/universal-storage-module Commented Aug 4, 2021 at 16:35
  • @AmirhosseinShahbazi feels like a bazooka, but nice to see that those kind of solutions do exist. You should probably post this as an answer so that it could get accepted and upvoted by OP! Commented Aug 4, 2021 at 17:36

4 Answers 4

3

I found the solution:

I just installed nuxt-universal-storage module, that Amirhossein Shahbazi suggested. So I have just done this:

/pages/index.vue:

<script>
export default {
middleware: ['auth'],
  layout (context) {
    let currentRole = context.app.$storage.getUniversal('PROFILE_DATA')
    console.log(currentRole)
    let currentLayout = 'default'
    let defaultRoles = ['customer_support_manager', 'checker', 'storekeeper']
    let tabletRoles = ['deputy_cutting_shop']
    if (defaultRoles.includes(currentRole.role)) {
      currentLayout = 'default'
    }
    else if (tabletRoles.includes(currentRole.role)) {
      currentLayout = 'tablet'
    }
    return currentLayout
}
</script>

/middleware/auth.js:

export default function ({ redirect, app, store }) {
    // some token checkers for existing, for 401 error and for their validity
}
Sign up to request clarification or add additional context in comments.

3 Comments

So, you're probably using cookies here at some point. Glad that this solution works, meanwhile I'm still not sure why all of this code is in a layout(), it is not it's purpose. Do you render a 'blog' string or alike at the end? If not, this one should probably be a middleware, especially looking at the $router.push.
Yes, of course, I return the string at the end. I just check what role now is Vuex state and then choose what layout will be rendered :) Thank you for the help. So I moved the extra code to the middleware, and now my layout only has some ifs, where I choose what string I will return in the end
I'd still stuck with having a dynamic layout rather than dynamically changing layouts. You could make conditional in your layout. At least, I do prefer this approach.
0

If I'm not mistaken, Nuxt is the SSR solution for Vue (same as Next for React), right?

If so, you don't have access to the localStorage. Server Side is not running in your browser!

Comments

0

This kind of code works fine

<script>
export default {
  layout({ store }) {
    if (process.client) {
      console.log('localStorage?', localStorage.getItem('myCat'))
      console.log('store?', store)
    }
  },
}
</script>

Because localStorage is not available on the server.

Try to use localStorage.setItem('myCat', 'Tom'), move to your page and see how it displays the localStorage and the store (don't forget to use the context since this is not available here).

6 Comments

The code inside this condition does not run
Not sure what you're expecting to run there beyond a return 'blog' or alike inside of layout().
I need to define the user role in localStorage to choose what layout will be loaded next
I don't know why, but the code inside process.client condition doesn't work when I reload the page, but it works when the component is rerendered
Maybe I can check localStorage inside middleware, push the data to Vuex, if localStorage is not empty. And then inside layout check Vuex state? Or it will not work in that way?
|
0

You can use cookie-universal-nuxt

After login you can set "AUTH_TOKEN" as cookie instead of localStorage

window.$cookies.set('AUTH_TOKEN', token)

and you can access it in layout function as

layout (context) {
     let token=context.app.$cookies.get('AUTH_TOKEN')
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.