똑같은 삽질은 2번 하지 말자

Nuxt typescript 마이그레이션중 코맛타코토 No.1 (nuxt-property-decorator) 본문

Vue

Nuxt typescript 마이그레이션중 코맛타코토 No.1 (nuxt-property-decorator)

곽빵 2021. 5. 8. 18:20

Typescript를 적용할 때, Vue의 기본적인 hook들은 Vue와 거의 유사하므로 생략하고 마이그레이션하면서

중간중간 막힌 부분들 또는 미처 몰랐던 부분들을 여기서 써 나가고자 한다.

 

우선 공식문서

typescript.nuxtjs.org/

 

Nuxt TypeScript

TypeScript Support for Nuxt.js

typescript.nuxtjs.org

 

fetch hook ?

Nuxtv2.12에서 추가된 fetch 훅은 어떻게 쓰면될까?

일부 훅(fetch 같은)들은 Component.registerHooks을 써서 등록할 필요가 있다고 한다.

소스코드

Component.registerHooks(['fetch', 'fetchOnServer']);

@Component
export default class MyComponent extends Vue {
  async fetch() {};
  fetchOnServer() { return false };
}

참조

github.com/nuxt-community/nuxt-property-decorator/issues/72

 

New fetch and fetchOnServer - Nuxt 2.12.x · Issue #72 · nuxt-community/nuxt-property-decorator

Nuxt 2.12+ has changed the way fetch works. As the name is the same, this is thankfully supported by nuxt-property-decorator. However, it also introduces a new hook called fetchOnServer which is a ...

github.com

 


Error: Exporting mutable 'let' binding, use 'const' instead.

음 이건 공식문서에서 추천하는 방식으로 했는데 eslint에 걸려버린다..

그러면 그냥

import { NuxtAxiosInstance } from '@nuxtjs/axios';

// eslint-disable-next-line
let $axios: NuxtAxiosInstance;

export function initializeAxios(axiosInstance: NuxtAxiosInstance) {
  $axios = axiosInstance;
}

export { $axios };

좀 그렇긴한데 예외로 두는게 좋은거같다..

 


ERROR  [Vue warn]: Error in render: "TypeError: Cannot read property 'trim' of undefined"  

이건...에러를 찾는데 꽤 시간이 걸렸지만,

추가한 컴포넌트에 @Componenet 를 안써줘서 생긴에러이다.

렌더링하는데 컴포넌트라고 인식을 넉스트에서 못한 모양? 이다.


mutations -> commit

actions -> dispatch

 

actions 에서 왜 state에 바로 접근가능한데, 굳이 mutations을 이용해서 값을 셋팅하는걸까?

그건 Vue devtools에 '기록' 을 남기기 위해서이다. actions는 기록이 남지 않지만, mutations은 기록이 남기 때문에

기록은 우리가 개 같이 작성한 코드들을 디버깅을 할때 아주 아주 필요한 요소이니깐..

 


https://kamang-it.tistory.com/entry/Vue23computed-%EA%B7%B8%EB%A6%AC%EA%B3%A0-methods%EC%99%80%EC%9D%98-%EC%B0%A8%EC%9D%B4featwatch

 

[Vue-23]computed, 그리고 methods와의 차이(feat.watch)

JavaScript와 HTML, CSS등에 대해서는 일체 다루지 않는다. 기초지식은 다른 강의를 참조하도록 하라. 참고: [Package]Bower(Front End Pacakage 관리) 설치 [Package]Vue.js vue의 methods에 대해서 이 포스팅에..

kamang-it.tistory.com

위 글은 methods 와 computed의 차이를 서술한 기사인데,

computed는 template에 직접 연결된 태그의 값, 바꿔 말하면 dom의 변경이 일어날때,

자신과 직접 연결된 값이 변경되는것이 아니면 computed는 캐시에 저장된 값을 가상돔에 반환한다.

반면에 methods는 methods가 template에 직접 연결된 값이 있고(methods를 반응형 getter처럼 사용할 때)

dom의 변경이 일어날때, computed와 달리 캐시에 저장된 값을 반환하는게 아니라 method를 '실행' 시켜서 값을 반환해 준다는 것이다.

위의 기사에서는 빨간글씨에 대한 언급이 없어서 이해하는데 시간이 좀 걸렸다.

(처음에는 뷰의 데이터들이 변경되면 안에 있는 메소드들은 싹 다 실행되는줄;; )

 

아 computed에 대한 글을 찾아보게된 이유는 vuetify 의 validate의 함수내에서 data에 대한 접근이 잘 안되서 알아본 결과,

computed 로 바꾸면 접근이 되는걸 발견했다.

  emailRules: Function[] = [
    (v: string) => !!v || '이메일은 필수입니다.',
    (v: string) => /.+@.+/.test(v) || '이메일이 유효하지 않습니다.',
  ];

  nicknameRules: Function[] = [(v: string) => !!v || '닉네임은 필수입니다.'];
  passwordRules: Function[] = [(v: string) => !!v || '패스워드는 필수입니다.'];
  get passwordCheckRules(): Function[] {
    return [
      (v: string) => !!v || '패스워드확인은 필수입니다.',
      (v: string) => v === this.password || this.password + '비밀번호가 일치하지 않습니다.',
    ];
  }

위의 passwordCheckRules() 에는 이미 입력한 패스워드를 맞게 입력했는지 패스워드를 확인하는 검증단계인데,

this.password에 일반 다른 Rules처럼 작성하니 제대로 접근이 안되서 computed 로 바꿔준뒤에는 제대로 되었다.

그럼 왜? 일까 typescript를 마이그레이션 하기전에는 그냥 다른 룰처럼 적어도 잘 되었는데...

 


Persistenace (로그인 정보 유지)

vuex-module-decorators 에서 nuxtServerInit 으로 저장된 쿠키값으로 새로고침을 할 때도, 로그인 정보 가져오기를 하려고 한다.

nuxtServerInit 을 우선 store/index.ts 에 배치

import { ActionTree, Store } from 'vuex';
import { ActionContext } from 'vuex/types';
// import { Context } from '@nuxt/types';
import { initialiseStores } from '~/utils/store-accessor';

export const state = () => ({});
export type RootState = ReturnType<typeof state>;

const initializer = (store: Store<any>) => initialiseStores(store);
export const plugins = [initializer];

// Rootのactionsを追加
export const actions: ActionTree<any, any> = {
	nuxtServerInit: async (context: ActionContext<RootState, RootState>) => {
		await context.dispatch('users/loadUser');
	},
};

export * from '~/utils/store-accessor';

만일을 위해 말하는 거지만 store-accessor.ts는 공식문서하고 비슷해요~

/* eslint-disable import/no-mutable-exports */
import { Store } from 'vuex';
import { getModule } from 'vuex-module-decorators';
import Users from '~/store/users'; // module을 가져와서
import Posts from '~/store/posts';

let UserStore: Users;
let PostStore: Posts;

function initialiseStores(store: Store<any>): void {
	console.log('@@@@@@@@@@@@--InitialiseStores--@@@@@@@@@@@@@@');
	UserStore = getModule(Users, store); // 추가
	PostStore = getModule(Posts, store);
}

export { initialiseStores, UserStore, PostStore };

store가 어떻게 로드 되는지 꽤 공부가 됬던 이슈였다~

RootState는 index.ts에서 이미 로드되고

initializer에 의해 나머지 module store들이 로드

그리고 화면을 그리기 전에 키워드인 nuxtServerInit 이 실행되어진다.

여기서 nuxtServerInit에서 실행하고 있는 loadUser라는 함수가 서버에서 쿠키값으로 저장된 유저정보를 가져오는 함수인데,

$axios.get~~ 하고 return을 안해줘서(return $axios.get()) axios 부분을 기다리지 않고 화면들이 그려져서

새로고침을 해도 로그인이 유지 안되는것 처럼 보였다...

Comments