_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<P = {}, CP = {}, S = {}> extends React.Component<P & 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의 제네릭이다.
<P = {}, 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>
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를 직접 사용하지는 못했다.
조금 생각해보면 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 |