본문 바로가기

FrontEnd/React

타입 스크립트 Next.js의 인터페이스를 알아보자.

_app.js의 클래스 컴포넌트

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const store = () => {
  return createStore(Reducers, {}, composeWithDevTools(applyMiddleware(thunkMiddleware)))
}
 
class Myapp extends App<{ store: object }> {
  render(): JSX.Element {
    const { Component, store, pageProps } = this.props
    return (
      <Container>
        <Provider store={store}>
          <Component {...pageProps} />
        </Provider>
      </Container>
    )
  }
}
 
export default withRedux(store)(Myapp)
 
 

Redux에 연결된 _app.js 컴포넌트이다.

App 컴포넌트와 제네릭

일반적으로 React.Component를 상속받는 것이 아닌

App이라는 Next의 모듈을 상속받는다.

App은 다음과 같은 형태를 가진다.

1
2
3
4
5
6
7
8
9
10
11
12
export default class App<= {}, CP = {}, S = {}> extends React.Component<& AppProps<CP>, S> {
    static childContextTypes: {
        router: PropTypes.Requireable<object>;
    };
    static origGetInitialProps: typeof appGetInitialProps;
    static getInitialProps: typeof appGetInitialProps;
    getChildContext(): {
        router: import("next-server/dist/lib/router/router").NextRouter;
    };
    componentDidCatch(error: Error, _errorInfo: ErrorInfo): void;
    render(): JSX.Element;
}
 

여기서 주의 깊게 살펴봐야 할 점은 App의 제네릭이다.

<= {}, CP = {}, S = {}> 를 각각 받아야 하고 default일 경우 빈 객체여야만 한다.

 

다시 _app.js의 Myapp을 살펴보자

 

class Myapp extends App<{ store: object }> {

 

여기서 store를 제네릭에 추가해주지 않으면 App을 상속받는데 에러가 난다.

default일 경우에는 빈 객체를 받아야 하는데, props에 store를 사용한다면

애초에 없는 클래스(다형성)을 상속 받기 때문이다.

Container란 무엇인가?

Next에 제공하는 컴포넌트중 또 하나 Container 컴포넌트를 _app의 wrapper로 사용하였다.

   return (

      <Container>

        <Provider store={store}>

          <Component {...pageProps} />

        </Provider>

      </Container>

    )

<_app.tsx>

export declare function Container(p: any): any; // next/app
Container는 함수로 어떤 Parameter도 받고 어떤 Return값도 리턴하는 평범한 함수이다.
이를 통해 유추해보자면 Container라는 이름 그대로 Wrapper 역할 그 이상도 이하도 아닌것 같고 실제로 Cotaniner가 없다고 하더라도 앱에 문제는 없다.

declare

함수가 declare 라는 옵션이 붙은 채로 선언되어 있는데, 이 옵션을 통해 해당 변수가 전역 객체에 선언된다고 한다.

 

getInitialProps와 Props 타입 지정하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { NextPage } from "next";
 
const Index: NextPage = props => {
  console.log(props);
  return (
    <div className="IndexPage">
      <div>Index</div>
    </div>
  );
};
 
Index.getInitialProps = async () => {
  const test = {
    data: 1
  };
  return {
    test
  };
};
 
export default Index;
 
 

NextPage

getInitialProps를 가지는 인터페이스가 많지만 그중 next에서 제공하는 NextPage가 가장 이해하기도 사용하기도 쉽다.

getInitialProps를 이용하여 test를 초기 Props로 전했고, 콘솔에 찍히는 것을 확인 할 수 있었다.

 

하지만 test를 직접 사용하지는 못했다.

< props는 처음에는 빈 객체이다. >

조금 생각해보면 getInitialProps는 결국 코드가 실행된 이후에 발생되는 작업이기 때문에 컴파일 타임에서는 props가 빈 객체로 받아들여지는것도 납득이 된다.

interface로 타입 선언

자바를 사용해봤다면 알 수 있지만, 앞으로 만들어질 객체를 인터페이스로 타입을 주게 되면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
interface Iprops {
  test: {
    data: number;
  };
}
 
const Index: NextPage<Iprops> = (props: Iprops) => {
  console.log(props.test);
  return (
    <div className="IndexPage">
      <div>Index</div>
    </div>
  );
};
 

뿐만 아니라 이를 통해서 자연스럽게 타입 검사또한 할 수 있게 되었다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
interface Iprops {
  test: {
    data: number;
  };
  other: {
    data: string;
  };
  theOther: {
    data: boolean;
  };
}
 
const Index: NextPage<Iprops> = (props: Iprops) => {
  return (
    <div className="IndexPage">
      <div>{props.test.data}</div>
      <div>{props.other.data}</div>
      <div>{props.theOther.data}</div>
    </div>
  );
};
 
Index.getInitialProps = async () => {
  const test = {
    data: 1
  };
  const other = {
    data: "데이터"
  };
  const theOther = {
    data: false
  };
  return {
    test,
    other,
    theOther
  };
};
 

여러가지 Props를 받아보았다.

Redux 타입

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import { createAction, handleActions } from "redux-actions";
 
interface IinitialState {
  init: boolean;
  do: string;
}
 
export const initialState: IinitialState = {
  init: true,
  do""
};
 
export const REDUX_TEST: string = "REDUX_TEST";
export const REDUX_DO: string = "REDUX_DO";
 
export const actionTest = createAction(REDUX_TEST);
 
declare interface Ipayload {
  word: boolean;
  gogo: string; // dispatch에까지 영향을 미치지 않는다.
}
 
export const actionDo: Function = createAction(
  REDUX_DO,
  (payload: Ipayload) => payload
);
 
declare interface IreduxDoAction {
  payload: {
    word: string;
    gogo: string;
  };
//역시 영향을 미치지 않는다.
 
export default handleActions(
  {
    [REDUX_TEST]: state => {
      return {
        ...state,
        init: false
      };
    },
    [REDUX_DO]: (state: IinitialState, action: IreduxDoAction) => {
      return {
        ...state,
        do: action.payload.word
      };
    }
  },
  initialState
);
 
 

리덕스는 일반적인 방법으로는 연결된 React의 Dispatch와 작용되지 않는다.

예를 들어 gogo라는 값은 dispatch의 파라미터로 받지 않는다. 

또한 word는 string값으로 전달되지만 boolean으로 지정했다. 그럼에도 불구하고 에러없이 잘 실행된다.

Redux 파일 내부에서는 타입 검사를 하지만 React-Redux의 dispatch와 같은 값으로는 타입검사를 하지 않는 것을 확인 할 수 있다. 고로 유효한 타입은 다음 정도가 될 것 같다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import { createAction, handleActions } from "redux-actions";
 
interface IinitialState {
  init: boolean;
  do: string;
}
 
export const initialState: IinitialState = {
  init: true,
  do""
};
 
export const REDUX_TEST: string = "REDUX_TEST";
export const REDUX_DO: string = "REDUX_DO";
 
export const actionTest = createAction(REDUX_TEST);
 
export const actionDo: Function = createAction(REDUX_DO, payload => payload);
 
export default handleActions(
  {
    [REDUX_TEST]: state => {
      return {
        ...state,
        init: false
      };
    },
    [REDUX_DO]: (state: IinitialState, action) => {
      return {
        ...state,
        do: action.payload.word
      };
    }
  },
  initialState
);
 
 

 

'FrontEnd > React' 카테고리의 다른 글

next 보일러 플레이 pankod 분석하기  (0) 2019.08.22
Redux-Form  (0) 2019.07.04
[Apollo] Apollo start(1)  (0) 2019.05.10
[Redux]날씨 앱 오버뷰  (0) 2019.01.06
[Redux]리덕스_액션  (0) 2019.01.02