React
를 통해서 인스타그램 클론 코딩을 진행하면서 여러 일들이 있었지만 그 중에서 어려웠던 한 가지를 뽑자면 바로 Lifecycle
에 관련된 일이다. 정확하게 Lifecycle
에 대해서 모르는 상태로 관련 메소드를 사용하다 보니 여러 에러를 겪을 수 밖에 없었다.
React
에서 특히 클래스형 컴포넌트를 사용하는 경우에 화면이 그려지는 방식은 아래와 같다.
constructor()
가 호출된다.render()
메소드가 호출된다.componentDidMount()
가 호출된다.만약 내가 그리고자 하는(특히, Array.map()
을 이용해서 그릴 예정인) 데이터가 componentDidMount()
를 통해서 불러와야 하는 경우에는 아래와 같은 에러를 겪게 될 것이다.
나는 위의 상황을 정확히 알지 못했기 때문에 어째서 Array.map()
가 작동할 수 없는지에 대해서 많은 고민을 했다.
공식문서를 통해서 화면을 렌더링 할때 호출되는 순서에 따른 에러임을 알게 된 나는 componentWillMount()
를 사용했다. render()
보다 빠르게 호출되기를 원했기 때문이었다. 동작은 잘 되었지만 이는 옳은 방법이 아니었다.
리액트 공식문서에 따르면 componentWillMount
의 경우에 이름이 변경되기도 했으며, 추후 버전에서는 삭제될 예정이라고 한다. 이제는 getDerivedStateFromProps()
라는 메소드를 통해서 render()
전에 호출되도록 할 수 있지만 이는 매우 특별한 경우에만 사용하라고 되어있다.
그렇다면, 대안이 무엇일까. 이 역시 문서에 따르면 constructor()
또는 componentDidMount()
를 통해서 해결하는 방법을 권장하고 있다. 여기서 constructor()
의 경우에는 생성자 함수이기 때문에 되도록 초기화와 관련된 내용만 처리하는 것을 권장하고 싶다.
마지막으로 우리에게는 결국 되돌아와서 componentDidMount()
라는 선택지가 주어졌다. 이를 쓰기 위해서 우리가 해줄 수 있는 것이 바로 조건부 렌더링 이다.
웹페이지를 구성하다보면 특정 상황이나 조건에 따라서 화면을 렌더링해야하는 경우가 생겨날 수 밖에 없는데 이때 사용하는 것이 조건부 렌더링이다.
// && 연산자 사용
<ul>
{comments && comments.map(comment => (
<Comment
key={comment.id}
comment={comment}
onDelete={this.handleDelete}
onLike={this.handleLike}
/>
))}
</ul>
위의 코드를 보면 comments
가 true
라면 comments.map()
이 실행되도록 하고 있다. 위의 코드를 삼항연산자
를 통해서 작성할 수 있는데 단순히 false
경우에는 동작하지 않도록 하고 싶은 경우라면 &&
연산자가 가독성 측면에서 좋다.
위의 코드는 아래처럼 사용할 수도 있다.
// ?. 사용(optional chaining)
<ul>
{comments?.map(comment => (
<Comment
key={comment.id}
comment={comment}
onDelete={this.handleDelete}
onLike={this.handleLike}
/>
))}
</ul>
위는 ?.(optional chaining)
을 사용한 방식이다. 프로퍼티에 접근할 때 만약 null
이나 undefined
라면 단락하고 undefined
를 반환하는 방식이다. 남용하는 것은 유지보수에 좋지 않기 때문에 꼭 필요한 경우가 아니라면 지양하자.