首页 > 解决方案 > NuxtJS / Vuex | nuxtServerInit 和 fetchData 操作未填充用户状态

问题描述

使用 NodeJS、Express 和 MongoDB 构建 API,使用 JWT 和 Cookies 进行用户身份验证。使用 store (vuex) 使用 axios 服务从 API 获取用户数据。在 store 文件夹中创建了 auth.js,创建了 fetchData 操作,该操作从后端 (axios.get(apiRoute)) 获取数据并将用户设置为状态。想使用 nuxtServerInit 执行此操作,所以我在 store 文件夹中创建了 index.js 文件。添加了空状态和操作。Action 包含 nuxtServerInit,它使用 dispatch() 在 auth.js 中调用 fetchData 方法。

然而,在这一切之后,它根本不起作用。例如:用户已登录,但帐户页面未使用用户数据(姓名、电子邮件、图像等)呈现。

我尝试从 auth.js 中的 fetchData 操作返回一个承诺,但它不起作用。我还尝试在 index.js 文件中设置 fetchData 操作并直接在其上调用调度。

商店/auth.js

// Importing Files
import axios from 'axios';

// State
export const state = () => ({
    user: null
});

// Mutations
export const mutations = {
    SET_USER (store, data) {
        store.user = data
    },
    RESET_USER (store) {
        store.user = null
    }
};

// Actions
export const actions = {
    // Fetch User Account
    async fetchData ({ commit }) {
        try {
           const response = await axios.get('http://localhost:3000/api/v1/users/account');
            commit('SET_USER', response.data.doc);
            return response;
        } catch (err) {
            commit('RESET_USER');
        }
    }
};

存储/index.js

// State
export const state = () => ({

});

// Actions
export const actions = {
    async nuxtServerInit({ dispatch }) {
        console.log('Testing');
        const res = dispatch('auth/fetchData');
        return res;
    }
};

组件/Settings.vue

<template>
  <section class="data-block-wrap" v-if="user">
     <BlockHeader :blockHeaderName="`Welcome Back, ${user.name.split(' ')[0]}`" btnText="More Details" />
     <img :src="getPhotoUrl(user.photo)" alt="User Photo" class="user-data__image">
     <p class="user-data__short-bio">{{ user.shortBio }}</p>
  </section>
</template>

<script>
 export default {
    // Computed
    computed: {
        user() {
            return this.$store.state.auth.user;
        }
    }
    ...
 };
</script>

我希望在 Vue 组件上正确呈现用户数据,但目前它根本不起作用。渲染是静态的,没有来自数据库/ api 的数据显示。

编辑/更新

应用程序在 default.vue 文件(所有组件的“父”文件)中的 created() 挂钩上调用 fetchData 时正确呈现用户数据。

默认.vue

<template>
  <div class="container">
    <TopNav />
    <SideNav />
    <nuxt />
  </div>
</template>

// Importing Components
import TopNav from '@/components/navigation/TopNav';
import SideNav from '@/components/navigation/SideNav';
import axios from 'axios';

import { mapActions } from 'vuex';

export default {
  components: {
    TopNav,
    SideNav
  },
  methods: {
  // Map Actions
  ...mapActions('auth', ['fetchData']),
    async checkUser() {
      const user = await this.fetchData();
    },
  },
   // Lifecycle Method - Created
   created() {
    this.checkUser();
  }
}
</script>

标签: javascriptnode.jsvue.jsvuexnuxt.js

解决方案


似乎这里正在发生一些非常有趣的事情。问题是axios.get('http://localhost:3000/api/v1/users/account')从 nuxtServerInit() 内部调用。

这导致了本质上是无限递归。nuxtServerInit 调用http://localhost:3000,它会访问同一台服务器,再次运行 nuxtServerInit,然后调用http://localhost:3000,依此类推,直到 javascript 堆内存不足。

不要为此使用 nuxtServerInit,而是使用fetch方法:

fetch 方法用于在渲染页面之前填充存储,它类似于 asyncData 方法,只是它不设置组件数据。

注意:您在 fetch 中无权访问 Nuxt 组件,因此您必须使用上下文对象而不是“this”

// inside your page component
export default {
  fetch (context) {
    return context.store.dispatch('auth/fetchData');
  }
}

作为基本规则:

  • 使用 fetch 填充存储在服务器或客户端上的数据
  • 使用 asyncData 在服务器或客户端填充组件数据
  • 使用 nuxtServerInit 使用请求对象上的值设置存储,如会话、标头、cookie 等,这仅在服务器端需要

推荐阅读