보통 리액트를 처음 배울 때, componentDidMount
라는 것을 document.ready 에 해당한다고 배웠다. 그래서 잘 써먹었고 그게 Hooks로 넘어오면서 useEffect 라는 녀석으로 바뀌면서 사용법도 재밌어졌다. 오늘은 (결국은 내 머리의 문제) useEffect 를 다루면서 생겼던 문제를 적어보고자 한다.
코드가
useEffect(() => {
// 블라블라
return () => {
// unmount 시에 실행되는 부분
}
})
이렇게 구성된다. 그런데 재밌는 옵션이 있는게
useEffect(() => {
// 블라블라
return () => {
// unmount 시에 실행되는 부분
}
}, [])
이렇게 useEffect()
의 첫번째 인자는 함수가 들어오고 두번째 인자에는 배열을 넣게 되어있다. 저 배열의 의미가 뭘까?
결론부터 얘기하면 나의 머리가 문제였다. useEffect
는 이름에서 알 수 있듯이 뭔가 상호작용? 을 하는 원리로 돌아가게 되어있다. 그래서 기존의 componentDidMount
와 약간 다르다. 위에서 언급한, useEffect
의 두번째 인자로 넘겨주는 배열의 값에 따라서 (사실 배열이라고 해야알지.. 그냥 값을 대괄호로 감싼 건지 모르겠다. 배열이라면 여러 개를 담아볼텐데 아직 그런 예제를 본 적이 없다. 직접 해보는 수 밖에..)
만 useEffect
안쪽의 내용이 돌아가게 코드를 만들 수 있다.
내가 겪었던 문제는.. 컴포넌트가 마운트 된 후, 소켓으로 status를 받고 해당 status에 따라서 각기 다른 api를 호출하면 거기서 넘어오는 값을 받고. 그걸로 useState
를 해서 DOM을 만들어 내야아는 상황이었다. 보통 api에서 넘어오는 배열의 길이는 각자 다르지만 보통 21개 정도의 배열이 넘어온다.
그래서 쉽게 생각하면 api호출이 끝나고 useState
해야지 했는데 api를 지속적으로 호출시킨다. 백엔드 개발자가 뭐 전쟁났냐고 쫓아온다. 왜일까? 정확히는 수신한 배열의 길이만큼 계속 호출되고 호출되고 하면서 누적된다. 21개의 배열이 있으면 0번째가 21번을 호출하고.. 호출된 21개의 배열 중 0번째가 또 21번을 호출하는..
그래. 이게 소켓이벤트를 갖고 실행하니 그 소켓 들어오는 이벤트 만큼 실행되서 그럴거야! 라는 멍청한 생각을 해본다. 소켓이벤트의 경우는 잘개 쪼개놔서 초기에 로딩하는 부분은 한번 들어오고 코드블록이 실행되지 않는다.
이전 글에서 useState
는 컴포넌트를 지속적으로 리렌더링 한다고 했다. 그게 리액트 특성이고.. 아 그러면 useState
가 되는 만큼 컴포넌트가 새로 리렌더링 되니 useEffect
내에 있는 코드블록이 지속적으로 실행되서 이 난리가 나는구나. 라는 결론에 이르른다.
결국 오늘의 문제점 부분에서 언급한.. useEffect
의 두번째 인자 부분이 문제였다. 빈 배열([]) 을 넘기면 해당 useEffect
는 컴포넌트가 마운트 될 때, 딱 한번만 실행된다. 근데 요즘 잠시 다른 업무에 정신이 팔려서, 두 달만에 새로운 컴포넌트를 만들던 와중에 그걸 잊고 있었던 것이다. (정말 나는 야매로 먹고사는 개발자인가..) 그래서 이걸 잊지말고자 여기에 정리해 놓게 되었다.
사람은 늙으면서 머리도 같이 늙는 것 같다. 지속적인 코딩과 공부만이 이 바닥에서 먹고사는데 지장이 없게 해주는 지름길이다.