러쉬 클론 코딩 프로젝트에서 setstate의 비동기적 특성부분에 대해 알아가면서 에러를 고치고 리팩토링한 코드를 정리해보려한다!
class ProductList extends Component {
constructor() {
super();
this.state = {
productLists: [],
activeTab: 0,
};
}
componentDidMount() {
if (activeTab === 0) {
fetch(`${PRODUCTS_API} ${SORT[0]}`)
.then(res => res.json())
.then(data => {
this.setState({
productLists: data.results,
});
});
}
if (activeTab === 1) {
fetch(`${PRODUCTS_API} ${SORT[1]}`)
.then(res => res.json())
.then(data => {
this.setState({
productLists: data.results,
});
});
}
}
(렌더링 부분)
<form>
<select name="sorting" onChange={this.valueHandler}>
<option value="0">낮은가격순</option>
<option value="1">높은가격순</option>
</select>
</form>
(백엔드에서 준 내림차순,올림차순 api)
const SORT = ['ordering=priceAsc', 'ordering=priceDesc'];
처음에는 componentDidMount()
에서 if 문으로 activeTab의 state 값에 따라 fatch를 하는 코드를 두 번 작성했다. 반복되는 부분이 눈에 밟히고 변화되는 부분이 보였다.
1) 우선 fetch 함수를 따로 빼서 호출 해야겠다는 생각이 들었다.
2) sort [0][1]은 아래 render에서 받아오는 value값과 동일하니 바로 activeTab
값 자체를 넣어주면 되겠다는 생각이 들었다!
class ProductList extends Component {
constructor() {
super();
this.state = {
productLists: [],
activeTab: 0,
};
}
componentDidMount() {
const { activeTab } = this.state;
this.sortHandler(activeTab);
}
sortHandler = activeTab => {
fetch(`${PRODUCTS_API}&${SORT[activeTab]}`)
.then(res => res.json())
.then(data => {
this.setState({
productLists: data.results,
});
});
간결해지고 state 값이 변하면서 동적으로 api주소가 바뀔수 있도록 했다.
후련!
valueHandler = e => {
this.setState(
{
activeTab: Number(e.target.value),
},
setState의 비동기적 특성 때문에 activeTab의 값은 바뀌더라도 componentdidmount
는 화면을 처음 렌더하고 (한 번 실행이 되고) 끝나기 떄문에
가격순 정렬 값을 클릭해도 아무리 valueHandler
메소드로 이벤트 값이 바뀌어도 변하지 않는 에러가 있었다.
해결할 수 있는 방법은 componentDidUpdate
를 사용하는 방법과 setState의 두번째 인자로 state값을 바꾸고 실행할 함수로 콜백함수를 넣어주는 방법이 있다.
컴포넌트디드업데이트는 무한 렌더링이 될 수도 있는 경우가 발생할수 있어 컨트롤 하기 힘든 부분이 있다.
setState의 두번째 인자로 콜백함수를 사용하였다.
valueHandler = e => {
this.setState(
{
activeTab: Number(e.target.value),
},
() => this.sortHandler(this.state.activeTab)
);
};
콜백함수에 대해서도 처음에는 헷갈렸는데!
콜백함수를 쓰는 이유는 내가 쓴 코드의 예를 보면 렌더부분의 select option을 클릭해서 바꿀때 마다(onChange) 변하는 값을 기다렸다가 함수를 실행해야 하기 때문이다!
그래서 처음에는this.sortHandler(this.state.activeTab)
을 호출 했을 때는 아무런 변화가 없었다.
setState의 비동기적 특성과 함께 콜백함수에 대해 다시 한번 알아볼수 있었던 소중한 코드였다. 멘토님들께서 리뷰해주시면서 비동기적 특성에 대해서 팁을 주신 부분도 있었지만
if문과fatch 부분을 간결화 하는 작업은 오롯이 나의 머리 속에서 나왔던 발상이였기 때문에 오 이렇게 해볼까 될것 같은데 될까? 했는데! 됐다는 것을 처음으로 느껴서 감탄한 첫 코드였다.
더욱 감탄한 이유는 왜냐면 이렇게 하면 되지 않을까? 해서 (마음대로 로직을 짜고 실패하는) 안되었던 경험이 쌓이면서 내가 생각한 것이 디폴트로 틀리고 시작하겠다라는 생각을 가지고 있었고 자신감이 없었는데!
점점 그래도 답을 찾아가는 능력이 생기고 있구나라고 처음 느끼게 되었다.
그래서 나에게는 더 의미가 깊고 소중한 코드이다.
몇 일 지나고 그리고 나중에 더 성장한뒤에 보면 어떻게 보면 정말 간단한 코드처럼 보일 것 같다. 그 때마다 이 때를 잊지 않고 초심으로 돌아가는 포인트로 삼아야겠다!