티스토리 뷰
컴포넌트
(Arrow Function으로) 컴포넌트를 만들어본다.
import React from "react";
const App = (props) => {
const { sessionList } = props.store; //비구조화 할당을 해줌
return (
<div>
<header>
<h1>Reacct and TypeScript</h1>
</header>
<ul>
{sessionList.map((session) => (
<li>{session.title}</li>
))}
</ul>
</div>
);
};
export default App;
컴포넌트 분리
지난번에 언급했듯, 코드 작성 시 몇가지 원칙들이 있다.
'네이밍은 잘 지어야 한다.'와 같은.
상위에서 성격이 다른 것을 분리한다. 이 때, 언제 쪼갤지, 어떻게 잘게 쪼갤지 고민해야한다.
추후 코드가 비대해지기 전에 아래처럼 컴포넌트를 쪼개도록 해보자.
import React from "react";
const SessionItem = ({title}) => (
<li>{title}</li>
)
const App = (props) => {
const { sessionList } = props.store; //비구조화 할당을 해줌
return (
<div>
<header>
<h1>Reacct and TypeScript</h1>
</header>
<ul>
{sessionList.map((session) => (
<SessionItem title={session.title} />
))}
</ul>
</div>
);
};
export default App;
상태 만들기
그런데, 위의 컴포넌트는 상태가 없다. '정렬' 상태를 만들어보자.
const App = (props) => {
const { sessionList } = props.store;
const orderedSessionList = sessionList.map((session, i) => ({
...session,
order: i
}))
return (
...
);
};
orderedSessionList를 추가해준다. 기존 sessionList에 order 항목을 추가해주는 코드이다.
클래스 컴포넌트에서의 상태
class 컴포넌트는 new로 생성하고 render()를 실행해 주므로 값이 바뀌었을때 render를 실행할 수 있다.
리액트가 변화를 감지할 수 있도록 setState()를 실행하면 된다.
class ClassApp extends React.Component {
constructor(props) {
super(props);
this.onToggleDisplayOrder = this.onToggleDisplayOrder.bind(this);
this.state = {
displayOrder: 'ASC' //기본값을 넣어줌
}
}
onToggleDisplayOrder() {
this.setState({
displayOrder: displayOrder === 'ASC' ? 'DESC' : 'ASC'
})
}
이렇게 함수를 선언문으로 작성할 경우 this는 실행 컨텍스트를 따르므로 컨텍스트를 위해 this를 bind 해주어야한다.
반면, arrow function은 렉시컬 컨텍스트이므로 컴파일 타임의 흐름대로 문맥상 this를 알 수 있다.
클래스 컴포넌트에서는 상태가 여러 메소드에 분산되어있다.
class ClassApp extends React.Component {
constructor(props) {
super(props);
this.state = {
displayOrder: 'ASC'
}
}
toggleDisplayOrder = () => {
this.setState({
displayOrder : displayOrder === 'ASC'? 'DESC': 'ASC'
})
}
render() {
return(
<div>...
<button onClick={this.toggleDisplayOrder}></button>
</div>
)
}
}
함수형 컴포넌트에서의 상태
함수형 컴포넌트는 원래 상태를 가질수 없다. 하지만 hook을 쓰면 가능해진다.
const App = (props) => {
const [displayOrder, toggleDisplayOrder] = React.useState('ASC')
const { sessionList } = props.store;
const orderedSessionList = sessionList.map((session, i) => ({
...session,
order: i
}))
const onToggleDisplayOrder = () => {
toggleDisplayOrder(displayOrder === 'ASC' ? 'DESC': 'ASC')
}
return (
<div>
<header>
<h1>Reacct and TypeScript</h1>
</header>
<p>
전체 세션 갯수 : 4개
</p>
<button onClick={onToggleDisplayOrder}>재정렬</button>
<ul>
{orderedSessionList.map((session) => (
<SessionItem title={session.title} />
))}
</ul>
</div>
);
};
클래스 컴포넌트와 달리 상태가 응집성을 가지고 있다.
* 함수형 컴포넌트에서 dispatcher는 콜백으로 받아야한다.
* 참고로, hook자체는 closure가 아니다.
useEffect(() => {
구독()
return () => {
구독해제()
}
})
hook의 하나인 useEffect는 위와 같이 사용할 수 있다.
이 함수는 리액트 바깥에서의 사이드 이펙트를 몰아놓은 코드 즉, 사이드 이펙트가 생기는 일들을 처리하는 함수이다.
리턴을 함수로 해주면 UI에서 사라질떄 호출을 해준다.
비동기와 Generator
Generator
function* foo() {
}
Async
async function bar() {
}
둘 다 Promise와 밀접한 관계가 있다.
const x = 10;
const y = x * 10;
위의 코드는 동시에 실행이 불가하다
const x = () => 10;
const y = x() * 10;
이렇게 하면 x가 지연호출이 된다.(x값이 호출되는 시점에 결정됨)
Promise는 이 지연과 유사하다.
Promise
const p = new Promise(function(resolve, reject){
//Promise는 두개의 함수를 전달하기 위해 함수를 받음
resolve()
}
p.then(function(r) {
}
자바스크립트 클로저 때문에 Promise 안에 있는 다른 함수 안에 넣어 코드를 지연 시킬 수 있다.
const p = new Promise(function(resolve, reject){
setTimeout(() => {
resolve()
}, 1000)
}
Generator
funtion* make() {
return 1;
}
const i = make();
//일반적인 함수의 경우 i = 1
//제너레이터는 객체를 리턴함
제너레이터는 실제로 코루틴 함수의 구현체이다.
함수는 입력값을 받고 계산을 한뒤, 리턴을 한다. * 리턴이 없는건 프로시져
그런데 리턴을 여러번 할 수 있는 것이다.
다시 함수가 호출될때 마지막 리턴 지점부터 다시 시작한다.
(어떤 값을 계속 생산해내는 거라 명칭이 제너레이터인듯)
function* makeNumber() {
let num = 1;
while(true){
yield num++ //yield는 제너레이터 안에 리턴의 의미로 사용됨
}
}
const i = makeNumber();
위의 코드는 호출시 리턴되는 객체이고, 실행될 준비만 한다.
i.next()를 했을때 실제로 제너레이터 함수가 실행이 된다.
그리고 값이 아닌 객체를 반환한다.
→ 제너레이터 함수 바깥에선 끝났는지 여부를 체크할 수 없으므로 done이라는 플래그를 넘겨주기 위해서이다.
yield는 return 처럼 함수를 끝내는 게 아니라 값만 반환하는 역할이다.
.next() 메소드를 호출하면 yield가 있는 곳까지 코드가 실행된다.
이 것은 마치 바깥쪽 영역과 커뮤니케이션하는 느낌이다.
next()에 파라미터로 값을 넘기면 yield가 받을 수도 있다.
const delay = ms => new Promise((resolve) => setTimeout(resolve, ms));
function* main() {
yield delay(3000);
console.log('3sec');
} // 동기코드처럼 보임
const it = main(); //아직 호출안됨
const { value } = it.next() //promise 객체가 옴
value.then(() => {
it.next();
})
delay(3000).then(() => {
console.log('3sec');
})
generator는 함수 바깥쪽에서 안쪽을 제어하고, 안쪽에서는 비동기도 동기처럼 풀 수 있다.
이런방식을 쓰는게 바로 Redux-saga이다.
yield는 iterable한 객체를 반환하며, 프라미스가 아닌 상황에서도 사용할 수 있다.
Async
async function main2() {
await delay(3000);
console.log('3sec');
}
main2();
Promise에 최적화 되어있다. Generator와 달리 다음에 Promise가 와야한다.
이 내부도 Generator로 구성되어 있다.
'React' 카테고리의 다른 글
[우아한테크러닝 3기 : React&TypeScript] 6일차 - Webpack, Redux-saga (0) | 2020.09.17 |
---|---|
[우아한테크러닝 3기 : React&TypeScript] 5일차 - 미들웨어 (0) | 2020.09.15 |
[우아한테크러닝 3기 : React&TypeScript] 3일차 - React 구현, Hook (0) | 2020.09.08 |
[우아한테크러닝 3기 : React&TypeScript] 2일차 - 함수, Redux (0) | 2020.09.03 |
[우아한테크러닝 3기 : React&TypeScript] 1일차 - Overview (0) | 2020.09.01 |
- Total
- Today
- Yesterday
- 웹팩
- 배치처리시스템
- 1day1algorithm
- 프로그래머스
- 리액트
- sort()
- sort
- js
- Props
- 구간합
- 알고리즘
- 타입스크립트
- redux-saga
- Array
- 운영체제
- React
- 멀티프로그래밍
- javascript
- 배열
- Webpack
- 컴퓨터공학
- Algorithm
- 자바스크립트
- reduce()
- 시분할시스템
- 자료구조
- 우아한테크러닝
- greedyAlgorithm
- Typescript
- OS
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |