본문 바로가기
스파르타코딩클럽/내일배움캠프

[TIL] 내일배움캠프 React 과정 2023.01.12

by heereal 2023. 1. 13.

Today I Learned

  • React Native 팀 프로젝트 진행

useEffect와 useFocusEffect

useFocusEffect(
    useCallback(() => {
      getPostlist();
    }, [])
);

디테일 페이지에서 좋아요를 누르고 뒤로 가기 했다가 다시 해당 게시물 페이지에 들어가면 DB에는 반영이 됐지만 화면에는 좋아요가 반영되지 않는 문제가 발생했다. 원래는 useEffect로 getPostList라는 데이터를 불러오는 함수를 실행했는데 useEffect는 최초 렌더링 시 한 번만 실행이 되고 메인->디테일->메인으로 다시 돌아왔을 때는 useEffect가 실행되지 않았다.

 

그래서 useEffect 대신 useFocusEffect를 사용해서 화면에 포커스가 갈 때마다, 즉 메인 페이지에 들어갈 때마다 getPostList가 실행되도록 해서 메인->디테일->메인->디테일로 다시 들어갔을 때 좋아요를 최신 데이터 내역으로 불러올 수 있도록 수정했다.

 

PayloadTooLargeError: request entity too large encountered two children with the same key

이런 에러도 만났는데 메인 페이지에서 useEffect로도 getPostList를 실행하고 useFocusEffect로도 getPostList를 실행해서 발생한 문제였다.

 

 

본문 리스트에서 게시물 하나를 클릭했을 때 params를 어떻게 넘겨줄지에 대한 고민

{postlist.map(
    (post, index) =>
      mbticheck(post) && (
        <View key={index}>
          <PostBox
            onPress={() =>
              navigate("Stack", {
                screen: "CommunityDetail",
                params: { getPost: post },
              })
            }
          >
}

원래는 PostBox를 클릭했을 때 params로 post.id를 넘겨주고 이것을 이용해서 전체 postList에 find 메서드를 이용해서 특정 게시물의 정보를 가져와 화면에 보여주려고 했는데 이렇게 하면 find 메서드 때문에 약간 비효율적일 수 있겠다는 생각이 들었다. 

 

그래서 id를 넘기는 것이 아니라 post 객체 전체를 넘겨서 이것을 화면에 보여주면 속도도 개선되고 불필요하게 데이터를 읽을 필요가 없겠다는 생각이 들었다. 어차피 본문의 경우에는 수정을 다른 페이지에서 하니까 수정하고 다시 디테일 페이지로 넘어왔을 때 post를 갱신할 계획이었다. 

 

근데 이렇게 하면 메인->디테일->수정 페이지로 params가 그대로 넘어가게 되는데 수정->디테일 페이지로 돌아갈 때 DB의 데이터를 수정해 주는 것과 별개로 params를 받은 그대로 디테일 페이지에 넘겨줘야 한다.

 

{
    name: "Stack",
    params: {
      screen: "CommunityDetail",
      params: { getPost: {...getPost, title, content} },
    },
},

그래서 수정->디테일 페이지로 params를 넘길 때 그냥 디테일에서 받아 온 getPost를 가공해서 넘겨버렸다. 사실 이렇게 하면 DB의 데이터와 화면에 보여지는 데이터가 달라질 위험이 있기 때문에 좋은 방법은 아닌 거 같다. 메인페이지에 들어가서 특정 게시물을 클릭했을 때만 디테일 페이지에 최신 데이터를 불러올 수 있는 구조가 된다. 쿼리를 써볼까도 생각했지만 본문의 CRUD를 전부 쿼리로 수정하기엔 시간이 부족하다고 생각되어 결국 본문 수정 기능은 이렇게 구현했다.

 

 

Firestore onShapshot으로 데이터 불러와서 RefreshControl 사용하기?

// 새로고침하기.
const onRefresh = async () => {
    setIsRefreshing(true);
    await getPostlist();
    setIsRefreshing(false);
};

<RefreshControl> 컴포넌트를 이용해서 메인 본문 리스트를 새로고침할 수 있게 해주고 싶었는데 firestore의 데이터를 불러오는 onSnapshot 메서드는 비동기 함수를 사용할 수 없기 때문에 setIsRefreshing이 정상적으로 작동하지 않는다. 이렇게 작성하면 await에 '이 식의 형식에 영향을 주지 않습니다.'라는 메시지가 뜬다. 그래서 그냥 메인페이지에 로딩 중이라는 것을 보여주는 기능은 포기했다. 이것도 쿼리를 사용했다면 가능했을 텐데😥

 

 

디테일 페이지 코드 최적화하기

export default function CommunityDetail({ }

	return(
        <>
          <ScrollView>
            <Post getPost={getPost} />
            <CommentsList getPost={getPost} />
          </ScrollView>
          <CommentAddInput getPost={getPost} />
        </>
    )
);

코드를 수정하다가 CommunityDetail에서 getPost 함수로 본문 데이터를 불러오고 CommunityDetail의 하위 컴포넌트인 Post 안에서도 getPost 함수가 또 한 번 실행되고 있다는 것을 발견했다. 이것은 불필요한 구조라는 생각에 CommunityDetail에서 useEffect로 getPost를 실행하던 부분을 삭제하고 하위 컴포넌트인 Post 안에서만 useEffect로 getPost를 실행하도록 했다.

 
 

회고

프로젝트 마감날이라 팀원과 새벽 6시까지 zep에 남아서 코드를 수정했다. 버그가 있었다기보다는 전체적으로 CSS를 다듬고, 유저의 편의성을 고려하며 코드를 최적화하는 과정이었다. 체력적으로 힘들긴 한데 솔직히 가끔씩 새벽 내내 코딩하면서 달리는 것도 재밌는 거 같다ㅋㅋ 재밌는 이유는 서로의 의견을 공유하며 더 나은 정답을 찾아나가는 그런 느낌이랄까... 아무튼 이번 프로젝트도 마지막까지 최선을 다해 마무리한 거 같다. 근데 나는 왜 항상 프로젝트 마감을 쫓기듯이 하는 것일까?🤨

 

내가 오늘 한 일

본문 수정 기능 구현, 커뮤니티->상황문답으로 복사하기

 

 

댓글