Is there a way to render the vuex module in nuxt prior to rendering the middleware?

I am facing an issue where the middleware renders before Vuex when the page is reloaded. This causes a problem as I need to change a value in Vuex based on the user's authentication status. Due to this sequence, the middleware returns the initial value of Vuex first. As a result, if the user is authenticated, it initially shows false and then true after Vuex is rendered. By that time, the middleware has already finished loading, leading to redirecting the user to the login page whenever the page is refreshed. Is there a way to prioritize loading Vuex before the middleware?

Here is the middleware code:

export default async function ({ store, redirect }) {
  // If the user is not authenticated
  const authenticated = await store.state.signup.authenticated
  if (!authenticated) {
    console.log(!authenticated)
    return redirect('/login')
  } else {
    console.log('I am logged in')
  }
}

Here is the Vuex code:

import axios from 'axios'

export const state = () => ({
  authenticated: false,
  credential: null,
})

export const mutations = {
  ADD_USER(state, data) {
    state.credential = data
    state.authenticated = true
  },
  LOGOUT(state) {
    state.credential = null
    state.authenticated = false
  },
}

export const actions = {
  async addUser({ commit }, data) {
    try {
      const response = await axios.post(
        'http://localhost:8000/api/rest-auth/registration/',
        data
      )
      commit('ADD_USER', response.data)
      this.$router.push('/')
    } catch (error) {
      return console.log(error)
    }
  },

  async addUserLogin({ commit }, data) {
    try {
      const response = await axios.post(
        'http://localhost:8000/api/rest-auth/login/',
        data
      )
      commit('ADD_USER', response.data)
      this.$router.push('/')
    } catch (error) {
      return console.log(error)
    }
  },
}

export const getters = {
  loggedIn(state) {
    return !!state.credential
  },
}

Here is the login.vue code

<template>
  <client-only>
    <div class="container">
      <v-card max-width="500" class="margin-auto">
        <v-card-title>Sign up</v-card-title>
        <v-card-text>
          <v-form @submit.prevent="submitUser">
            <v-text-field
              v-model="data.username"
              label="Username"
              hide-details="auto"
              append-icon="account_circle"
            ></v-text-field>
            <v-text-field
              v-model="data.password"
              label="Password"
              hide-details="auto"
              type="password"
              append-icon="visibility_off"
            ></v-text-field>
            <v-card-actions>
              <v-btn color="success" type="submit" class="mt-4" dark>
                Signup
              </v-btn>
            </v-card-actions>
          </v-form>
          <p>
            Don't have an account? <nuxt-link to="/signup">Register</nuxt-link>
          </p>
        </v-card-text>
      </v-card>
    </div>
  </client-only>
</template>

<script>
export default {
  data() {
    return {
      data: {
        username: '',
        password: '',
      },
    }
  },

  methods: {
    submitUser() {
      this.$store.dispatch('signup/addUserLogin', this.data)
    },
  },
}
</script>

<style lang="scss" scoped>
.margin-auto {
  margin: 2rem auto;
}
</style>

Answer №1

Indeed, there is a solution for your situation! The store you need is already present in your middleware, but currently empty. You must retrieve the necessary data and populate the store.

I recommend referring to the documentation on Nuxt middleware https://nuxtjs.org/guide/routing#middleware. It explains that

A middleware can be asynchronous. To achieve this, simply return a Promise or use the 2nd callback argument.

To address your issue, you should return a Promise within your middleware: this Promise will encompass the axios request. Here's a suggestion:

export default function ({ store, redirect }) {
    return new Promise(resolve => store.dispatch('signup/addUserLogin', data).then((user) => {
        if (!user) {
            // User not found
            redirect('/login');
        } else {
            // Perform actions with the obtained user, such as committing to the store
            resolve();
        }
    })
}

In your case, adjust the addUserLogin action accordingly: solely include the axios query here, excluding the redirect logic. Furthermore, you may face an issue with data used in the action, like password and user details being lost upon refresh. Consider implementing a token system, such as JWT, and storing them in local storage or cookies (as shown in this example https://nuxtjs.org/examples/auth-external-jwt/).

I hope this information proves helpful!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

JavaScript cannot properly plot data for stacked bar charts on highcharts

I am encountering an issue with plotting data in a bar highchart. Despite having values when I alert them, they do not appear on the barchart. I am using the following code snippet: chart.series[i].addPoint(data[i]['total_check']);. I am unsure i ...

AngularJS service for exchanging information among controllers

I am working on an AngularJS application (1.4.10) where I need to share data between two controllers. To achieve this, I created a factory: .factory('CardsForService', function($http, URL){ var service = { "block_id": '', ...

What is the process for accessing getters and mutations within a Vuex module?

As I make the transition to using Vuex instead of my custom store object, I have come across some challenges with understanding the documentation in comparison to other resources within the Vue.js community. For example, if I have a Vuex module named &apos ...

What is the process for deleting a token from local storage and displaying the logout page in Next JS?

I developed a Next.js web application and am looking to display a logout page when the token expires, while also removing the expired token from local storage. How can I ensure that this functionality works no matter which page the user visits within the a ...

Getting star ratings from the "rating" field in an array of objects using JavaScript

I am dealing with an array of objects that looks like this: var test_data = [ { "id" : "Test01", //Must be a string form ID "test_info" : "This is the test information", "tes ...

Can you explain the process of sending an AJAX request and managing it on a web server coded in C?

Could someone please provide an example of an AJAX request that retrieves a global variable stored on a webserver written in C? I am unfamiliar with JQuery and AJAX, so I would appreciate any guidance on how to accomplish this task. Thank you in advance ...

Chrome version 83 encounters an issue preventing file uploads

I recently updated my Chrome browser to version 83 and encountered some issues with certain forms that utilize an "Ajax upload" component. Despite researching the problems associated with this new version (https://developers.google.com/web/updates/2020/05/ ...

Identify the specific tab that initiated the request

Here's a puzzling question that may not have a straightforward solution, but I'm willing to give it a try. Recently, I developed a brilliant one-page application where each open tab "registers" itself with the server upon startup, indicating its ...

Steps for displaying a website within a specific Div using HTML

I'm trying to set up a website to open within a specific <div> tag, like the example shown in this link: Responsive. Can anyone spot what I'm doing incorrectly? <html> <head> <script> function mobile320() { ...

Using jQuery or JavaScript to adjust the bottom margin

Looking to Add Bottom Margin for Selection Box I have attempted the following CSS: #Selection { margin-bottom:23px; } Unfortunately, this method did not work for me. Is there a way to achieve this using JavaScript or jQuery? View Example on JsFiddle S ...

Swap information in one array with information from a different array

I am working with two arrays: const data = [ { id: 0, identifier: 'free-2020', name: '<I18nText id="pricing.plans.name.free" />', planTitle: 'free', price: '00', ...

Extract the initial line in the grid

I was wondering if there is a way to automatically copy the first value of a row in a grid to all the remaining rows. For example, if I have two columns A and B, and I input a value in column B at the first row, can that value be automatically populated in ...

Identify when the user clicks on the URL bar or types in the browser's address bar using Jquery or JavaScript

In my current project, I'm faced with the challenge of interacting with the browser's URL bar. Specifically, I need to detect events using jQuery/JS when a user clicks on the address bar, types in it, or switches tabs. Is there a way to achieve t ...

Rotate Array Elements by N Spaces in JavaScript

Implement a function called "rotate" that will take an array and return a new array with the elements rotated by n spaces. If n is positive, the array should be rotated to the right. If n is negative, then it should be rotated to the left. If n is 0, the ...

What is the best way to extract the modal into its own file?

Greetings, fellow React developer who is new to the field! I have successfully implemented a React Class Component that includes a popup Modal. This Modal displays when a user clicks on an Item Card: import React from 'react'; import { Card, Bu ...

Tips for enhancing the refresh rate of OpenLayer Vector layers with 200 elements

I am working on developing a timemap that combines the jquery-ui slider component and the OpenLayer library. I am utilizing the Vector layer of OpenLayers with Rules style for this project. map = new OpenLayers.Map('map', {maxResolution:'a ...

Looking to show an image when a checkbox is ticked and hide it when it is unticked in HTML?

How do I make a specific image appear when a user clicks on a checkbox? I'm unsure if I should use jQuery, Ajax, or another method. What is the best approach for this task? Your assistance would be greatly appreciated. I have successfully created the ...

When the form is submitted, send the information and automatically launch a PDF document

When a form is submitted after HTML validation, I need to both send data to Salesforce and open a link to a PDF file. The form is located within a modal and receives data from the parent component. <form class="mt-6" @submit.prevent="submitForm(tru ...

Vue.js creates a new row in the table with an undefined array of data

Trying to create a new row when clicking "+" using Vue Js Encountering an error: tablerows is not defined Vue.component('inp-row', { props: ['data'], template: `<tr :id="data.row_id" ><td> 1</td><td>2 < ...

Encountering problem while exhibiting server's response message within a modal popup in Angular 6

I have implemented two custom dialog modals in an Angular component. The objective is to open the appropriate modal and display the response message. The component receives two values as Observables from my services: The name of the modal that needs to ...