유명한 담벼락

데이터를 가져온 뒤 옵셔널 체이닝과 null 병합 연산자

by 담담이담
import { useQuery } from "@tanstack/react-query";
import Post from "./Post";
import styles from "./PostList.module.css";
import { getPosts } from "../api";

function PostList() {
  const { data: postsData } = useQuery({
    queryKey: ["posts"],
    queryFn: getPosts,
  });
  const posts = postsData?.results ?? [];
  return (
    <div className={styles.postList}>
      {posts.map((post) => (
        <Post key={post.id} post={post} />
      ))}
    </div>
  );
}

export default PostList;

 

import Card from './Card';
import ContentInfo from './ContentInfo';
import styles from './Post.module.css';

function Post({ post }) {
  return (
    <Card className={styles.post}>
      <div className={styles.content}>
        <ContentInfo user={post.user} updatedTime={post.updatedAt} />
        <p className={styles.description}>{post.content}</p>
      </div>
    </Card>
  );
}

export default Post;

맨날 모르겠던 그거.. 대체 언제 옵셔널 체이닝과 null 병합 연산자를 사용해서 예외처리를 해주는 거지?

 

여기서 useQuery의 결과 값은 다음과 같다.

 

이를 {data : postsData}로 받았다는 건 이 결과값의 data 프로퍼티 이름을 가진 값을 구조분해해서 사용하겠다는 것이다.

또한 :postsData라고 씀으로써 구조분해와 동시에 이름을 변경해주었다. 

 

우리가 원하는 건 postsData.results이다.

 

그래서 코드를 const posts = postData.results라고 접근할 수도 있지만, 저렇게 방어적으로 코드를 작성하는 이유는 다음과 같다.

 

만약 데이터를 불러와서 postData가 null이나 undefined라면 results라는 프로퍼티에 접근했을 때 에러가 발생할 것이다.

ERROR
Cannot read properties of null (reading 'results') TypeError: Cannot read properties of null (reading 'results')

그래서 옵셔널 체이닝을 이용해 postData?.results로 접근한다.

 

또한 postData?.results의 값이 null이나 undefined라면 map 메소드로 접근하고자 할 때 배열이 아니기 때문에 .map으로 접근할 수 없어 다음과 같은 에러가 발생한다. 

ERROR
Cannot read properties of null (reading 'map') TypeError: Cannot read properties of null (reading 'map')

따라서 results가 null이나 undefined라면 빈배열로 초기화해준다.

 

빈배열로 초기화해주면 에러가 나지 않고, map에서 아무것도 리턴되지 않는다.

 

 

 

 

+ map을 여러번 돌릴 경우에 발생할 수 있는 에러 

  const linksData = data ? data.map(formatLinkRawData).map(mapLinksData) : [];
  // const linksData = data?.map(formatLinkRawData).map(mapLinksData) ?? [];

아래 주석 처리한 코드처럼 작성했더니 또 TypeError: data.map is not a function라는 에러가 났다..

하 ㅠ 결론은 data?map(formatLinkRawData)를 해주면 data가 첫 렌더링 시 data가 null 일 때  data?map(formatLinkRawData)의 반환값이 undefined인데 거기서 또 map을 돌리려고 하니 나는 에러이다.. 

 

위처럼 조건부 렌더링으로 작성해주면 해결된다.

왜냐면 애초에 data가 있어야 map을 돌고 데이터가 있을 때 그 map을 돈 결과는 당연히 배열일 것이기 때문이다.

블로그의 정보

유명한 담벼락

담담이담

활동하기