리액트 컴포넌트는 라이프 사이클을 기준으로 동작하기 때문에 작성된 코드가 어떤 순서로 렌더되는지 예측 하기 위해 라이프사이클에 대한 이해가 중요하다.
constructor
→ render
→ componentDidMount
(주로 초기 데이터를 불러오는 작업을 여기서 함) → render
→ componentDidUpdate
(최초 렌더 이후 상태값 변화가 생긴 경우) → componentWillUnmount
constructor
생성자 함수로 컴포넌트 내에서 관리해야할 상태값이 있을 때 상태값을 할당하여 생성해준다.
componentDidMount
컴포넌트가 렌더 된 후(실제 돔에 JSX 코드가 연동된 후) fetch 함수를 이용하여 데이터를 불러오기 좋은 위치이다.
componentDidUpdate
최초 렌더 이후 데이터를 불러오는 등의 비동기적인 데이터 변화가 일어나야하는 경우 실행된다.
componentWillUnmount
이벤트나 setInterval 함수 종료로 컴포넌트 제거가 필요한 경우
부모 컴포넌트에서 최초 렌더 이후 업데이트가 일어난 경우 자식 컴포넌트에게도 영향을 주지만
자식 컴포넌트에서 업데이트가 일어나면 자식 내에서만 변경이 일어난다.
최초 렌더시에 브라우저는 코드 한줄한줄을 실행하게 되면서 자식 컴포넌트를 만나게 되면 자식 먼저 렌더 후 부모로 돌아와서 componentDidMount를 실행하게 된다.
map
에러컴포넌트에서 data를 불러오고 해당 data를 map 메소드를 이용하여 필요한 부분이 렌더되도록 사용할때 'map' of undefined 라는 에러가 뜨는 경우가 있다.
✨ data를 불러오는 작업은 componentDidMount()
내에서 이루어지는데 render()
단계에서는 아직 데이터가 불러지지 않는 빈 배열인 상태이므로 map을 작업할 배열 요소들이 존재하지 않는 상태이다. 이런 경우는 조건부 렌더링을 사용하여 배열이 존재하는 경우 배열을 이용한 map 작업이 되도록 조건문을 작성해준다.
class BestItems extends React.Component {
constructor() {
super();
this.state = {
bestItemsList: []
}
}
componentDidMount() {
fetch('/data/shoplist.json')
.then((res) => res.json())
.then((data) => {
this.setState({
bestItemsList: data["PRODUCT_LISTS"]
})
})
}
render() {
const {bestItemsList} = this.state;
return(
<section className="BestItems">
<h1>베스트 제품</h1>
//배열 데이터의 요소들이 존재하는 경우 map 메소드를 사용한 작업이 실행된다.
{ bestItemsList && bestItemsList.map((data) => {
return(
<BestItem key={data.id} name={data.name} url={data.url} />
)
})}
</section>
)
}
}
export default BestItems
반드시 어떠한 조건이던지 결과가 필요한 경우는 삼항연산자 한 조건에만 결과가 필요한 경우는 조건부 렌더링을 사용한다.