front/react

useEffect 첫 렌더링 방지 및 중첩으로 data request를 해야할 때, 중첩 axios 사용할 때 발생하는 오류 해결

jeong_ga 2022. 8. 8. 13:05

회사의 디테일한 정보를 확인하는 companyDetail 컴포넌트를 작성하는 도중, 작업중에는 발생하지 않았지만 배포 후에는 오류가 뜨는 것을 확인하였다.

작업중는 이미 data를 가져온 상황에서 이미지에 대한 axios를 진행했기 때문에 오류가 발생하지 않았었지만! 배포 및 새로고침하여 발생한 렌더링 상황에서는 detail data를 가져오기도 전, 해당 data를 이용하여 이미지 data를 가져오려 했기 때문에 발생한 오류였다.

 

 

그래서! 아래와 같이 코드를 수정하여 작성하였다.

  • useEffect를 이용하여 detailData의 값이 변화될 때 image data를 가져오는 axios를 실행하도록 코드를 설정
  • useEffect의 첫 렌더링 시 발생하는 오류(첫 렌더링 image axios를 진행하면 앞서 말한 문제로 인해 오류가 발생됨)를 해결하기 위하여 custom hook을 만들어 사용
  • 첫 렌더링 시 발생하는 오류! 를 해결하기 위해 image의 값이 true일 때 해당 태그를 사용할 수 있도록 {image && <tag />} 의 방식으로 작성

 

코드 확인

import { Link } from "react-router-dom";
import { useEffect, useState, useRef } from "react";
import { useParams } from "react-router-dom";
import {
  axiosPostToken,
  getStorage,
  useDidMountEffect,
} from "../Services/importData";
import { urlGetCompanyDetail, urlGetImages, ISLOGIN } from "../Services/string";

function Company() {
  let { cid } = useParams();
  const [companyDetail, setCompanyDetail] = useState([]);
  const [image, setImage] = useState();
  const reqImgs = useRef(null);
  const token = getStorage(ISLOGIN);

  useEffect(() => {
    axiosPostToken(
      urlGetCompanyDetail,
      {
        rcid: cid,
      },
      token
    ).then((res) => {
      if (res.status === "success") {
        setCompanyDetail(res.data);
        reqImgs.current = res.data.titleImg + "," + res.data.imgs;
        return;
      }
      if (res.status === "fail" && res.emsg === "process failed.") {
        alert("정보가 없습니다. ");
        return;
      }
    });
  }, []);

  useDidMountEffect(() => {
    axiosPostToken(
      urlGetImages,
      {
        imgs: reqImgs.current,
      },
      token
    ).then((res) => {
      console.log(res);
      setImage(res.data);
    });
  }, [companyDetail]);

  return (
    <div className="mainWrap">
      <section>
        <h3 className="blind">사업자 상세정보 관리</h3>
        <div className="paddingBox commonBox">
          <ul className="detailPageLayout">
            <li className="titleImg">
              {image && (
                <img src={image[0].storagePath} alt="사업자 대표 이미지" />
              )}
            </li>
            <li className="imgsImg">
              <ul>
                {image &&
                  image.map((item) => (
                    <li>
                      <img
                        key={item.iid}
                        src={item.storagePath}
                        alt="사업자 상세 이미지"
                      />
                    </li>
                  ))}
              </ul>
            </li>
          </ul>
          <div className="bigButton widthCenter">
            <Link className="Link" to="setcompanydetailInfo">
              사업자 정보 수정
            </Link>
          </div>
        </div>
      </section>
    </div>
  );
}
export default Company;

 

custom hook

import { useEffect, useRef } from "react";

export const useDidMountEffect = (func, deps) => {
  const didMount = useRef(false);

  useEffect(() => {
    if (didMount.current) func();
    else didMount.current = true;
  }, deps);
};

출처 :

 

Make React useEffect hook not run on initial render

According to the docs: componentDidUpdate() is invoked immediately after updating occurs. This method is not called for the initial render. We can use the new useEffect() hook to simulate

stackoverflow.com

 

 

이미지로 확인하기