[state 분리] - setState안되는 문제 #React + JS

🚨 useRef + IntersectionObserver + state 충돌

원인이 맞는지는 모르겠지만 `Ref`와 `Observer` 를 넣어준 DOM 요소에서 사용하는 state값을 변경하려고 하니 데이터는 변경이 되는데 리렌더링은 되지 않는 문제가 발생했다.  문제를 찾게 된 계기는 혹시나 해서 ref를 지워봤더니 setState가 제대로 동작을 했다. 

 

 

문제 코드

{displayedPosts.map((post, index) => (
  <StyledPostBox key={post.id} ref={getObserverRef(index, displayedPosts, observerRef)}>

// 기타 생략 ..

setState가 안 되던 state가 `displayedPosts` 이다. 데이터 구조는 대강 이렇게 생겼다. 

 

displayedPosts 구조

const [displayedPosts, setDisplayedPosts] = useState([
  {
    id: 100,
    content: "게시글 내용",
    likes: [], // 좋아요를 누른 사용자 ID 배열
    comments: [], // 댓글 배열
  },
  // 다른 게시글들...
]);

 

게시글 객체가 배열 형태로 존재하고 각 게시물의 좋아요, 댓글에 상호작용을 하면 해당 post에 해당하는 객체의 `likes`, `comments` 를 수정하도록 했다. (setState하는 코드는 생략)

 

작성한 코드는 문제가 없어보이고 실제로도 데이터의 변경은 잘 이루어졌다. 근데 렌더링하는 부분이 매우 이상하게 동작되었다. (사진이 들어간 게시글은 잘 렌더링이 된다거나.. 불변성을 무시하고 setState를 해주어야 렌더링이 된다거나..)

 

이후에 혹시나 싶어 ref를 지웠더니 동작이 잘 되는 것을 확인했다. 그리고 한숨을 쉬고 `게시글`과 `좋아요/댓글` state를 분리하기로 결정했다.

 

💡 state 분리

기존에 `displayedPosts` 에 묶여있던 `likes`와 `comments` 를 분리하기로 결정했다. 해시테이블 과 비슷한 형태로 분리했다. 

 

{
 [postId]: {
   isLike: true,
   likeCount: 12,
   comments:[{/*댓글...*/}]
 }
 ....
}

 

각 key에 postId를 매핑시켰고 좋아요와 댓글 정보를 넣어주었다. 

 

📍 정리

문제의 정확한 원인은 파악을 못했지만 대강 `Ref`와 `IntersectionObserver` 의 문제인걸로 생각이 든다. 충돌로인해 불필요하게 state의 분리를 하며 코드가 늘어났지만 좋은 해결 방법이었다...

 

댓글

Designed by JB FACTORY