Troubleshooting- UseEffect()관련 렌더링 과정에 대한 오류

Isabel·2022년 4월 27일
0

당근마켓 클론 코딩을 하는 과정에서 게시글을 클릭하면 상세페이지를 보여주려고 하는데 데이터를 불러오지 못하고 계속 useEffect에서 에러가 발생하였다.
useEffect를 이해하지 못한 데서 발생하는 에러같았다.

useEffect(() => {
dispatch(postActions.getAPost(postID));
})

그래서 useEffect를 정리하고자 글을 작성한다.

useEffect

useEffect를 사용하여 컴포넌트가 렌더링 이후에 어떤 일을 수행해야하는 지를 React에게 전달할 수 있다. React는 useEffect안의 함수(aka. effect) 를 DOM 업데이트를 수행한 이후에 불러낸다.

useEffect((parameter) => {callback함수},[dependancy array])

useEffect는 처음에 렌더링 된 이후에 한번 실행되고, 그 다음에 useEffect안에 작성되는 dependancy array의 값이 변경되면 다시 실행되게 된다. 혹은 useState를 같이 쓸 경우, state값이 업데이트될 때마다 실행된다.

  • useEffect를 컴포넌트 안에서 불러내는 이유: 컴포넌트 안에서 useEffect를 사용하면 useEffect안의 함수가 state와 props에 쉽게 접근할 수 있다.

아래는 내가 이번에 프로젝트를 하면서 에러가 발생했던 부분을 발췌해온 것이다.

import React, { useState } from "react";
import styled from "styled-components";
import Text2 from "../elements/Text2";
import { useHistory, useParams } from "react-router";
import { useDispatch, useSelector } from "react-redux";
import { actionCreators as postActions } from "../redux/modules/post";

const PostDetailPage = (props) => {
  const history = useHistory();
  const dispatch = useDispatch();

  // 파라미터로 postID값 받아옴
  const params = useParams(); 
  const postId = parseInt(params.postId);
  const userId = useSelector((state) => state.user.userId);
  //서버에서 response로 받아온 값 (Detail) - 가져오는 데 걸리는 시간 있을 수 있음. 
  //옵셔널 체이닝을 사용하여 데이터가 아직 없을 경우에는 넘어가고, 데이터가 있으면 .post로 불러옴
  const response = useSelector((state) => state.post?.post);
	
  React.useEffect(() => {
    dispatch(postActions.getAPost(postId));
  },[]);

 //state가 바뀌면 rerendering이 되면서 response가 생기게 되면 아래 return 내용 출력해서 문제를 해결함
  if(!response){  
    return <div></div>
  }
  return(
    <DetailWrap>
      <ArrowBackIosIcon onClick={()=>history.goBack()}></ArrowBackIosIcon>
      <HomeIcon onClick={()=>history.push('/')}></HomeIcon>
        <ImageWrap> 
          <img src={response.imageUrl}/>
        </ImageWrap>
        <DetailContentWrap>
          <UserInfoWrap>
            <ProfileImg src={} alt={response.userName}/>
            <div >
              <Text2 >{response.userName}</Text2>
              <Text2 >{response.location}</Text2>
            </div>
          </UserInfoWrap>
          {/* 게시글 제목 */}
          <TitleWrap>
            <Text2>{response.postTitle}</Text2>
          </TitleWrap>
          {/* 게시글 카테고리 및 게시 시간 표기 */}
          <CategoryWrap>
          <Button onClick={()=> history.push('/')}>{response.category}</Button>
            <Text2 >  {response.createdAt} 올림 </Text2>
          </CategoryWrap>
          <ContentsWrap>
            <Text2>{response.postContents}</Text2>
          </ContentsWrap>
          <LikedWrap>
            <Text2 >관심 {response.likeCount}</Text2>
          </LikedWrap>
          <LikesNPriceWrap>
            <Like like={like} onClick={toggleLike} {...props}/>
            <Text2> {response.price}</Text2>
            <Button>채팅하기</Button>
          </LikesNPriceWrap>
        </DetailContentWrap>
    </DetailWrap>
  );
};
`
export default PostDetailPage;

비동기처리로 인해서 서버에서 아직 불러오지 못한 데이터가 있을 경우, 프론트에서는 기다리지 못하고 에러가 나버렸다. 이를 방지하기 위해서 기다리는 차원에서
useState로 redux에서 state를 받아올 때는 옵셔널 체이닝을 사용하여 데이터가 없어도 컴파일 에러가 발생하지 않고 null값을 리턴하게 하였다.
그리고 아래 컴포넌트들을 리턴할 때

if (! state ) {
	return <div></div>
}

를 써주니 데이터를 못 불러올 때는 잠시 아무것도 보여주지 않으면서 기다렸다가 state를 불러올 수 있을 때 그 때 화면을 출력하여 에러를 해결할 수 있었다. 거의 뭐 만병통치약 수준이었다..!!!

이번 주부터 잘 써먹어야지!! 큑

0개의 댓글