SENTENCE U | Day 11 (전체 글 가져오기/반응형 레이아웃/글 상세페이지)

블로그 이사 완료·2023년 1월 26일
0
post-thumbnail

전체 글 가져오는 기능 Hook으로 만들어 사용

전체글을 가져오는 기능을 필요로 하는 페이지가 점점 많아지다보니 페이지마다 동일한 코드를 작성할 수 없었다.

그래서 Hook으로 만들어 필요한 정보를 리턴해 원하는 페이지에서 데이터를 가져가다 쓸 수 있도록 했다.

문제는 useQuery로 받아온 데이터는 객체로 받는데 보통 객체를 배열로 변환하는 함수를 사용하곤 하지만 무슨이유인지 배열로 변환할 수가 없었다.

그래서 아래와 같이 for in문을 사용해 객체 하나씩 돌면서 원하는 배열에 저장하는 방법을 사용할 수 밖에 없었다.

export const useGetAllposts = () => {
  const { data: postData, error } = useQuery(
    ['allPosts'],
    async () => {
      return await axios
        .get('/api/posts')
        .then((res) => {
          return res.data;
        })
        .catch((error) => {
          console.log(error);
        });
    },
    {
      cacheTime: Infinity, // 캐싱 시간
      refetchInterval: 10000, // 10초 주기로 리패치
    },
  );

  let posts = [];
  let postId = [];
  let postDate = [];
  let userName = [];
  for (let key in postData) {
    posts.push(postData[key].sentence);
    postId.push(postData[key].postId);
    postDate.push(postData[key].createdDate);
    userName.push(postData[key].userName);
  }

  return { postData, error, posts, postId, postDate, userName };
};

사용하고자 하는 페이지에서는 아래 코드 한줄로 데이터와 원하는 배열을 가져올 수 있게 됐다.

  const { posts, postId, postDate, userName, error } = useGetAllposts();

반응형 레이아웃 추가

메인 홈페이지의 가로폭에 따라(브레이크포인트) 데스크탑, 랩탑, 태블릿, 모바일의 홈페이지 레이아웃을 바꾸려고 반응형 웹디자인을 사용했다.

원래 홈 컴포넌트의 스타일에서 grid-area를 사용했는데, 그걸 이용하여 브레이크포인트마다 gride-template-areas를 수정해서 간편하게 적용 할 수 있다.

export const Main = styled.div`
  min-height: calc(100vh - 120px);
  display: grid;
  grid-template-areas:
    'poster poster poster poster poster poster . top top top . liveusers'
    'poster poster poster poster poster poster . top top top . liveusers'
    'poster poster poster poster poster poster . recent recent recent . liveusers'
    'poster poster poster poster poster poster . recent recent recent . liveusers'
    'poster poster poster poster poster poster . recent recent recent . liveusers';
  @media screen and (max-width: ${LAPTOP}) {
    grid-template-areas:
      'poster poster poster top top top top . liveusers'
      'poster poster poster top top top top . liveusers'
      'poster poster poster recent recent recent recent . liveusers'
      'poster poster poster recent recent recent recent . liveusers'
      'poster poster poster recent recent recent recent . liveusers';
  }
  @media screen and (max-width: ${TABLET}) {
    grid-template-areas:
      'top top top top . liveusers'
      'top top top top . liveusers'
      'recent recent recent recent . liveusers'
      'recent recent recent recent . liveusers'
      'recent recent recent recent . liveusers';
  }
  @media screen and (max-width: ${MOBILE}) {
    grid-template-areas:
      'top'
      'poster'
      'recent'
      'liveusers';
  }
`;

area는 너무 코드가 지저분하니 기본적으로 사용하는 rows와 coloumns를 사용하는 것이 더 좋을 것 같긴하다.


글 상세페이지 이동 에러 해결

홈페이지의 최신글이나/베스트글의 포스틀를 누를 경우 Postpage 컴포넌트로 이동하게 되는데 그때 전달해주는 postId의 props가 항상 postId배열의 0번만 보내주도록 코드를 작성해놨다.

posts.map((post, i) => (
          <Post
            key={i}
            post={post}
            postId={postId} // 모든 포스트에 postID props로 배열전체를 보냄
            postDate={postDate[i]}
            userName={userName[i]}
          />
))
posts.map((post, i) => (
          <Post
            key={i}
            post={post}
            postId={postId[i]}
            postDate={postDate[i]}
            userName={userName[i]}
          />
))

props를 보낼 때 해당하는 포스트의 인덱스 번호를 사용해서 해당 postId만 보낼 수 있게 됐다.

따라서 Post 컴포넌트에서 받은 postId는 배열이 아닌 한개의 포스트만 가르키는 값이기 때문에 API요청 시에도 에러가 발생하지 않는다.

const Post = ({ post, userName, postDate, postId }) => {
  const navigate = useNavigate();

  const onPostHandler = () => {
    axios
      .get(`api/posts/${postId}`, { withCredentials: true })
      .then((res) => {
        navigate(`/posts/${res.data}`);
      })
      .catch((err) => console.log(err));
  };

  return (
    <PostWrap onClick={onPostHandler}>
      <Title>{post}</Title>
      <Date>{postDate}</Date>
      <Name>{userName}</Name>
    </PostWrap>
  );
};

글마다 고유의 postId로 navigate시키는 것을 볼 수 있다.

profile
https://kyledev.tistory.com/

0개의 댓글