React의 개발 방식의 가장 큰 특징은 페이지 단위가 아닌, 컴포넌트 단위로 시작한다는 점이 가장 큰 특징이다.
페이지를 만들기 이전에 컴포넌트를 만들고 조립한다.
즉, 상향식(bottom-up)으로 앱을 만드는 것이다. 이렇게 하면 가장 큰 장점은 테스트가 쉽고 확장성이 좋다. 그래서 여러분이 기획자나 PM, 또는 UX 디자이너로부터 앱의 디자인을 전달받고 나면, 이를 컴포넌트 계층 구조로 나누는 것이 가장 먼저 해야 할 일이다.
단일 책임 원칙에 따른 구분에 따라 하나의 컴포넌트는 한 가지 일만 한다.
그렇기에 보통 트리 구조로 나타낼 수 있으며 데이터를 어디에 둘 지를 결정해야 한다.
컴포넌트는 컴포넌트 바깥에서 props를 이용해 데이터를 마치 인자(arguments) 혹은 속성(attributes)처럼 전달받을 수 있다.
즉 데이터를 전달하는 주체는 부모 컴포넌트가 되고 이는 데이터 흐름이 하향식(top-down) 임을 의미한다.
컴포넌트는 props(부모로부터 받는 데이터)를 통해 전달받은 데이터가 어디서 왔는지 전혀 알지 못한다.
우리는 변하는 값과, 변하지 않는 값을 각각 state와 props로 볼 수 있다.
상태 즉, state로 두어야 하는지 여부는
- 부모로부터 props를 통해 전달되면 state가 아니고
- 시간이 지나도 변하지 않으면 state가 아니고
- 컴포넌트 안의 다른 state나 props를 가지고 계산 가능하다면 그렇다면 state가 아니다.
그렇다면 상태를 어디에 위치시켜야 할까?
상태가 특정 컴포넌트에서만 유의미하다면, 특정 컴포넌트에만 두면 되니까 크게 어렵지 않지만, 만일 하나의 상태를 기반으로 두 컴포넌트가 영향을 받는다면 이때에는 공통 소유 컴포넌트를 찾아 그곳에 상태를 위치해야 한다.
즉, 두 개의 자식 컴포넌트가 하나의 상태에 접근하고자 할 때는 두 자식의 공통의 부모 컴포넌트에 상태를 위치해야 한다는 것이다.
그렇게 상태 위치를 전부 정하고 나서 보니, 어떤 경우에는 부모 컴포넌트에서의 상태가 하위 컴포넌트에 의해 변하는 것을 어렵지 않게 발견할 수 있다. 새로운 것을 추가하는 경우가 대표적인 예로 생각할 수 있는데 이럴 땐 부모의 상태를 변화시켜야 한다.
하위 컴포넌트(NewTweetForm)에서의 클릭 이벤트가, 부모의 상태를 바꾸어야만 하는 상황에 이를 어떻게 해결할 수 있을까? 여기서 "State 끌어올리기(Lifting state up)"를 이용한다.
상태를 변경시키는 함수(handler)를 하위 컴포넌트에 props로 전달해서 해결할 수 있다. 콜백 함수를 사용하는 방법과 비슷하다.
props를 언급할 때 어제도 이야기한 순수 함수라는 것을 토대로 말해보자면
사이드 이펙트가 있으면 순수 함수가 아니다.
함수 컴포넌트를 만들 시에 사이드 이펙트가 있으면 안 된다.
우리는 setState를 사용하여 상태를 변환할 수 있는데
setState 사용할 때 이전 상태 사용 시 콜백을 사용해서 해결한다면 우리가 기존 내용에 어떠한 이벤트로 추가할 때 더욱 손쉽게 구현할 수 있다.
1
2
3
4
|
this.setState(ele => { //callback 함수로 다음 상태를 만들어내는 역할
return { tweets: [...ele.tweets, newTweet] } // 기존에 있는 것은 그대로 가져오고(...ele.tweets) 새로 추가되는 것 추가(newTweet)
}) // 그렇게 되면 라이프 사이플 주기에 따른 리렌더링이 일어난다.
}
|
cs |
setState를 하게 되면 리 렌더링 되게 된다. 사용하지 않고 직접 대입하게 되면 변하지 않기 때문이다. 라이프사이클을 참고하면 된다.
Life cycle
1. 생성될 때 (생성)
2. 화면에 등장한(mount) 후 (생성) => componentDidMount
컴포넌트가 화면에 마운트(화면상에 컴포넌트가 등장할 때) 될 때 한번 불린다.
컨스트럭터 → 렌더 → componentDidMount
3. 새로운 props를 받을 때 (업데이트)
4. 새로운 상태를 가질 때 (업데이트)
5. 새로운 상태를 가지고 난 후 (업데이트) => componentDidUpdate
6. 화면에서 사라지기 (unmount) 후 (제거) => componentWillUnmount
매 중요한 순간마다 컴포넌트는 새로 렌더링 된다.
함수 컴포넌트에서는 라이플 사이클 메서드를 부를 수 없다 그렇기에 class 컴포넌트를 사용하여야 한다.
Life cycle을 사용하는 이유?
constructor, render에서는 fetch setTimout async/await 같은 비동기를 호출할 수 없다.
그렇기에 componentDidMount / componentDidUpdate에서는 비동기 호출을 할 경우나 상태를 가지고 다른 작업을 하여야 할 때 이 안에서 작업을 정의해 줄 수 있다.
예를 들자면 componentWillUnmount에 비워주거나 삭제하거나 해주는 것인 clearTimeout이나 removeEventListener 도 사용 가능하다.
react는 단방향 데이터 흐름이며 이는 데이터는 위에서 아래로 단방향으로 흐른다는 것을 의미한다.
이렇게 아래로 흐르는 데이터를 전달하는 방식은 props를 이용한다.
같은 레벨의(형제) 컴포넌트끼리는 상호작용을 할 수 없다.
그렇기에 같은 레벨의(형제) 컴포넌트끼리 상태를 공유하기 위해서는 공통의 부모에서 상태를 다루어야 한다.
'개념정리' 카테고리의 다른 글
1/7[TIL]React Hooks (0) | 2021.01.07 |
---|---|
1/6[TIL]React(3) (0) | 2021.01.06 |
1/4[TIL]React(1) (0) | 2021.01.04 |
12/30[TIL] Server & Node (0) | 2020.12.30 |
12/15[TIL]Deploy (0) | 2020.12.15 |