HTML, CSS, JS => 리액트화 시 어려웠던 점
useEffect안에서 closures
뷰 포트의 스크롤에 따른 섹션인덱스 값을 관리하기 위해 addEventListener scroll을 useEffect에서 걸었는데 eventListener의 callback 함수안에서 section index값이 변하지 않는 문제를 맞이했다.
⚠️scroll Event처럼 정말 예민한(?), 변화가 엄청 많은 이벤트 콜백함수안에서 setState를 사용한다는 것은 솔직히 좋지 못한 것이라고 생각한다. 내부에서 state가 변경될 때마다 리렌더링이 일어나기때문이다. 하지만 다행히도(?) 위 콜백함수 안에서는 뷰포트에 따른 섹션이 변경될 때만 setState가 작동하므로 사용하는 것이 무리없다고 생각하였다.
자, 문제로 돌아가서
위와 같이 했을 경우 스크롤을 계속 해도 scrollLoop함수 내부에서는 sectionIndex가 계속 0인 문제가 생겼다. 하지만 함수 밖에서는 잘 증가하였다. 왜지??
찾아본 결과 react hooks 에서는 closures를 사용하고 있다고 한다.
즉, useEffect 실행시점에 scrollLoop는 sectionIndex가 0인 렉시컬 환경을 기억하고 있는 것이다. 이후에 sectionIndex가 업데이트가 되어 새로운 함수가 생성되더라도 useEffect에서 기억하는 함수는 sectionIndex가 0인 함수를 실행하기 때문이다.
⛔️ sectionIndex가 변화하지 않으면 scrollLoop안의 로직은 무의미하기 때문에 로직을 작동시킬 수 있는 변화하는 section Index값이 필요했다.
돌파구 1. - useRef()
그래서 이후 useRef를 이용하여 section Index를 관리하려고 하였다.
하지만 변화하는 section Index에 따라 chlid component에서 사용을 해야하는데 ref는 불가능 하였기에 최종적은 해결법이 아니었다.
돌파구 2. - useState와 useRef() 혼용
현재 최종적으로 선택한 방법이다.
scrollLoop 내부 로직을 돌리기위해 변화하는 section index를 ref에 담아 사용하였고 ref가 변할 때마다 sectionIndex state도 업데이트해줘서 외부에서 state값을 이용해 section index 를 참조할 수 있게 되었다.
위 방법이 최적의 방법은 아니라고 생각한다. 따라서 좀 더 좋은 방법이 있다면 업데이트 하도록 하겠다.