programing

NuxtJS / Vuex | nuxtServerInit 및 fetchData 액션이 온 상태의 사용자를 채우지 않음

sourcetip 2022. 7. 9. 09:40
반응형

NuxtJS / Vuex | nuxtServerInit 및 fetchData 액션이 온 상태의 사용자를 채우지 않음

사용자 인증에는 JWT와 Cookie를 사용하여 NodeJS, Express 및 MongoDB를 사용한 API 구축store(vuex)를 사용하여 API에서 Axios 서비스를 사용하여 사용자 데이터를 가져왔습니다.스토어 폴더에 auth.js를 작성하고 백엔드(axios.get(apiRoute))에서 데이터를 GET하여 사용자를 state로 설정하는 fetchData 액션을 작성했습니다.nuxtServerInit을 사용하여 이 작업을 수행하고자 하여 스토어 폴더에 index.js 파일을 저장했습니다.빈 상태 및 액션을 추가했습니다.액션에는 dispatch()를 사용하여 auth.js의 fetchData 메서드를 호출하는 nuxtServerInit이 포함됩니다.

하지만 이 모든 일이 있은 후, 그것은 전혀 작동하지 않는다.예를 들어 다음과 같습니다.사용자가 로그인하고 있지만 계정 페이지가 사용자 데이터(이름, 이메일, 이미지 등)로 렌더링되지 않습니다.

auth.js의 fetchData 액션에서 약속을 반환하려고 했지만 작동하지 않았습니다.또한 index.js 파일 내에서 fetchData 액션을 설정하고 디스패치를 직접 호출해 보았습니다.

스토어/auth.module

// 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');
        }
    }
};

store/index.displaces

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

});

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

컴포넌트/설정.표시하다

<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에서 데이터가 표시되지 않습니다.

편집/갱신

기본적으로 fetchData on created() 훅을 호출하면 앱이 사용자 데이터를 올바르게 렌더링합니다.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>

여기서 아주 흥미로운 일이 벌어지고 있는 것 같아요.문제는 전화입니다.axios.get('http://localhost:3000/api/v1/users/account')nuxtServerInit() 내에서 지정합니다.

이것은 본질적으로 무한 재귀의 원인이 됩니다.nuxtServerInit이 콜을 발신하다http://localhost:3000는, 같은 서버에 히트 해, nuxtServerInit 를 재실행해, 콜 합니다.http://localhost:3000javascript 힙의 메모리가 부족해질 때까지 계속합니다.

이 경우 nuxtServerInit을 사용하는 대신 fetch 메서드를 사용합니다.

가져오기 방법은 페이지를 렌더링하기 전에 저장소를 채우기 위해 사용됩니다. 구성 요소 데이터를 설정하지 않는다는 점을 제외하면 비동기 데이터 방식과 비슷합니다.

참고: 가져오기 시 Nuxt 구성 요소에 액세스할 수 없으므로 "this" 대신 컨텍스트 개체를 사용해야 합니다.

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

일반적으로 다음과 같습니다.

  • 가져오기 기능을 사용하여 서버 또는 클라이언트의 저장소 데이터 채우기
  • 서버 또는 클라이언트의 컴포넌트 데이터를 채우려면 비동기 데이터 사용
  • nuxtServerInit은 필요한 서버측에서만 사용할 수 있는 세션, 헤더, 쿠키 등 요청 객체에 값을 사용하여 스토어를 셋업하는 경우 사용합니다.
    The solution to this question is to use the NuxtServerInt Action this way inside your store.js
    
    1. you will need to run  npm install cookieparser and npm install js-cookie
    
    const cookieparser = process.server ? require('cookieparser') : undefined
    
    export const state = () => {
      return {
        auth: null,
      }
    }
    export const mutations = {
      SET_AUTH(state, auth) {
        state.auth = auth
      },
     
    }
    export const actions = {
      nuxtServerInit({ commit }, { req }) {
        let auth = null
        if (req.headers.cookie) {
          try {
            const parsed = cookieparser.parse(req.headers.cookie)
            auth = parsed.auth
          } catch (err) {
            console.log('error', err)
          }
        }
        commit('SET_AUTH', auth)
      },
    }


Then in your login page component, you call your backend API, just like this 

import AuthServices from '@/ApiServices/AuthServices.js'
import swal from 'sweetalert'
const Cookie = process.client ? require('js-cookie') : undefined

 async onSubmit() {
      try {
        
        const body = {
          email: this.email,
          password: this.password,
        }

        const res = await AuthServices.loginUrl(body)
        console.log('res', res)
        console.log('res', res.data.message)
        setTimeout(() => {
          // we simulate the async request with timeout.
          const auth = {
            accessToken: res.data.payload.token, // from your api call, you get the user token 
            userData: res.data.payload.user,
          }
          swal('Logged in', `${res.data.message}`, 'success')

          this.email = this.password = ''

          this.$refs.loginForm.reset()
          this.$store.commit('setAuth', auth) // mutating to store for client rendering
          Cookie.set('auth', auth) // saving token in cookie for server rendering
          this.$router.push('/')
        }, 1000)
      } catch (error) {
        console.log('error', error)
        swal('Error!', `${error.message}`, 'error')
      }
    },


your AuthServices.js looks like this

import axios from 'axios'

const apiClient = axios.create({
  baseURL: `http://localhost:3000`,
})

export default {
  loginUrl(body) {
    return apiClient.post('/login', body, {
      headers: {
        'Content-Type': 'application/json',
      },
    })
  }
}




then you get the user data using computed in the navbar or say dashboard e.g to say Hi,Xavier

inside where you want place the user data, just add this
<template>
  <section>
     <p class="firtname_data">Hi, {{ user.firstnam }}</p>
  </section>
</template>

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



Hope this help... it worked for me 

것 요.await

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

언급URL : https://stackoverflow.com/questions/57104087/nuxtjs-vuex-nuxtserverinit-and-fetchdata-action-not-filling-user-on-state

반응형