2017.07 React with TypeScript 스터디 정리.


Component 만들어보기


component를 생성하는 방법에는 크게 3가지 방법이 있습니다.


1. stateless component - state를 쓰지 않는 component 입니다. -> 그냥 function 입니다!

2. react.component를 상속받아 만드는 component입니다. -> class 입니다.

3. react.purecomponent를 상속받아 만드는 component입니다. -> class 입니다.


그럼 일단 코드부터 보겠습니다.

create-react-app으로 생성된 프로젝트 폴더의

src/App.tsx 파일을 살펴보겠습니다.


import * as React from 'react';
import './App.css';

const logo = require('./logo.svg');

class App extends React.Component<{}, {}> {
render() {
return (
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>Welcome to React</h2>
</div>
<p className="App-intro">
To get started, edit <code>src/App.tsx</code> and save to reload.
</p>
</div>
);
}
}

export default App;


React.Component<P, S> - Generic

react.component 를 상속받아 만드는 컴포넌트는 props와 state를 generic으로 받아옵니다.

지금은 받아오는게 없으므로 아무것도 쓰여있지 않습니다.



props


props는 컴포넌트 외부에서 컴포넌트로 넣어주는 데이터로, 함수전달도 가능합니다.

이때, props는 컴포넌트 내부에서 자신의 props를 변경할수 없는 고정된 값입니다.

물론, 변경시켜서 다시 넣어주는것은 가능합니다.

이때 외부에서 props데이터를 변경시키면, 컴포넌트는 render함수를 재 호출하게 됩니다.




props 추가해보기


class App extends React.Component<{name: string}, {}> {
render() {
return (
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>Welcome to React</h2>
</div>
<p className="App-intro">
To get started, edit <code>src/App.tsx</code> and save to reload.
</p>
</div>
);
}
}

props의 데이터로 name이라는 string값을 가진 데이터가 들어올것이라고 정의한뒤,

npm run start를 통해 실행시키면, 오류가 발생합니다. 

왜냐하면, props는 컴포넌트 외부에서 전달되어지는 데이터인데, 아직 전달받는게 없기 때문입니다.


따라서 App component가 사용되어지는 src/index.tsx의 파일에서 props를 전달시켜 줍니다.

ReactDOM.render(
<App name="jaro"/>,
document.getElementById('root') as HTMLElement
);


* 추가적으로 App.test.tsx 파일도 변경해주어야 하지만, 저는 일단 test 파일은 지우고 포스팅을 진행하겠습니다.


자 그러면, 이제 props를 제대로 전달 받았는지 확인해봐야할거 같습니다.

App component의 render 부분을 수정하겠습니다.


class App extends React.Component<{name: string}, {}> {
render() {

const {name} = this.props;

return (
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>Welcome to React</h2>
</div>
<p className="App-intro">
Hello {name}
</p>
</div>
);
}
}


App-intro 부분을 수정하였습니다. name을 표시하는데, 그 name은 this.props의 name값으로 정의하였습니다.

수정뒤 코드를 저장하면, 자동으로 페이지가 다시 로드됩니다.


state


state는 컴포넌트 내부에서만 사용하는 데이터로, 클래스의 프로퍼티와는 다르게, 변경하면 특정 조건에 따라 render가 재 호출됩니다.

( defalut로는 무조건 다시 render합니다. 자세한건 다음에 포스팅 할 lifecycle에서 설명하겠습니다 )

state는 생성자 혹은 초기 할당으로 state를 생성해주어야 하고, 값을 변경할시에는 setState함수를 이용해서 변경하여야

render함수를 재 호출할수 있습니다.


state 추가해보기


class App extends React.Component<{name: string}, {age: number}> {

constructor(props: {name: string}) {
super(props);
this.state = {
age: 31
};
this._addAge = this._addAge.bind(this);
}

render() {

const {name} = this.props;
const {age} = this.state;

return (
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>Welcome to React</h2>
</div>
<h1>Hello {name}</h1>
<h1>age : {age}</h1>
<button onClick={this._addAge}>나이 추가</button>
</div>
);
}

private _addAge(): void {
this.setState({
age: this.state.age + 1
});
}

}


state로 number type의 age를 추가하였습니다.

생성자 함수에서 this.state 를 생성하였고, age의 초기값은 31로 하였습니다.

그리고 state값의 변화를 보기위해 버튼을 추가하여 _addAge라는 private함수를 생성하였습니다.



코드 수정후 저장을 하면, 브라우져가 다시 로드하여 위와 같은 화면이 나타나게 됩니다.

이때 나이추가 버튼을 누르면, state가 변하면서 새롭게 랜더링 되어 값이 변함을 확인할수 있습니다.



여기까지는 기본적인 props와 state의 사용법이었습니다. 

그렇다면 typescript의 장점을 살리는 과정을 추가해 보도록 하겠습니다.

바로 props와 state를 interface로 바꾸는 작업입니다.


interface AppProps {
name: string;
}

interface AppState {
age: number;
}

class App extends React.Component<AppProps, AppState> {

constructor(props: {name: string}) {
super(props);
this.state = {
age: 31
};
this._addAge = this._addAge.bind(this);
}

render() {

const {name} = this.props;
const {age} = this.state;

return (
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>Welcome to React</h2>
</div>
<h1>Hello {name}</h1>
<h1>age : {age}</h1>
<button onClick={this._addAge}>나이 추가</button>
</div>
);
}

private _addAge(): void {
this.setState({
age: this.state.age + 1
});
}
}


왜 interface를 쓰느냐??

프로젝트의 규모가 커지게 되면, 그만큼 props도 많아지고 state도 많아져서 관리에 어려움을 느낄수 있습니다.

또한 interface를 export를 하게 되면 다른곳에서도 이 인터페이스에 접근하여 파악할수도 있고,

모든 interface를 한 파일에 몰아넣어 관리할수도 있게 됩니다.

이 방법에 대해서는 경험으로 자신만의 정답을 찾아가시기 바랍니다.


소스코드의 주소입니다.

https://github.com/JaroInside/tistory-react-typescript-study/tree/5.component


터미널에서

git clone https://github.com/JaroInside/tistory-react-typescript-study.git


cd tistory-react-typescript-study


npm install ( yarn install )


git checkout 5.component


다음 포스팅에서는 stateless component에 대해 포스팅 하겠습니다.

감사합니다.



참고 슬라이드 - http://slides.com/woongjae/react-with-typescript-1#/
참고 동영상 - https://www.youtube.com/playlist?list=PLV6pYUAZ-ZoHx0OjUduzaFSZ4_cUqXLm0

'React > React&typeScript' 카테고리의 다른 글

7. LifeCycle  (0) 2017.07.12
6. stateless Component  (0) 2017.07.12
4. tsconfig & tslint  (0) 2017.07.09
3. CRA  (0) 2017.07.07
2. TypeScript  (0) 2017.07.07
블로그 이미지

Jaro

대한민국 , 인천 , 남자 , 기혼 , 개발자 jaro0116@gmail.com , https://github.com/JaroInside https://www.linkedin.com/in/seong-eon-park-16a97b113/

,