본문 바로가기

Front-End

[axios] 서버로 데이터 전송

사용자가 화면에서 정보를 등록하면 그 정보를 recoilstate을 통해 저장

-> 마지막 단계에서 recoil에 저장된 정보를 axios를 통해 서버로 보냄

 

정보를 서버로 넘겨줄 때 헤더에 access token도 함께 넣어서 보내줘야 했다.

 

import { styled } from "styled-components";
import { useRouter } from "next/router";
import { useState, useEffect } from "react";
import axios from "axios";
import { useRecoilValue } from "recoil";
import {
  registerHomeUpLoadFileState,
  registerHomeWholeInfoState,
} from "@/lib/states";

const RegisterComplete = () => {
  const router = useRouter();
  const handleGoCompleteButtonClick = () => {
    router.replace("/");
  };
  const uploadFile: object | null | string = useRecoilValue(
    registerHomeUpLoadFileState
  );
  const registerHomeWholeInfo = useRecoilValue(registerHomeWholeInfoState);
  console.log(uploadFile);

  useEffect(() => {
    handleUpload();
  }, []); // 페이지 로드 시 한 번만 업로드하도록 설정

  const handleUpload = async () => {
    if (uploadFile === null) {
      console.error("uploadFile is null");
      return;
    }

    const jsonRegisterHomeWholeInfo = JSON.stringify(registerHomeWholeInfo);
    const blobRegisterHomeWholeInfo = new Blob([jsonRegisterHomeWholeInfo], {
      type: "application/json",
    });

    const formData = new FormData();
    if (uploadFile instanceof File) {
      formData.append("files", uploadFile);
    } else if (uploadFile instanceof Blob) {
      formData.append("files", uploadFile);
    } else {
      console.error("Unsupported type for uploadFile");
      return;
    }
    formData.append("request", blobRegisterHomeWholeInfo);
    console.log(formData.get("files"));
    console.log(formData.get("request"));

    const access_token =
      "서버를_통해_받은_access_token";
    axios.defaults.headers.common["Authorization"] = `Bearer ${access_token}`;

    try {
      const uploadResponse = await axios({
        method: "post",
        url: "https://banggeul.store/properties",
        data: formData,
        headers: {
          "Content-Type": "multipart/form-data",
        },
      });

      console.log(uploadResponse); // 업로드 응답 확인
    } catch (error) {
      console.log(error);
    }
  };

  return (
    <StepsContainer>
      <RegisterHomeCompleteGif />
      <RegisterHomeCompleteMessage>
        내 집 등록하기가
        <br />
        완료됐어요!
      </RegisterHomeCompleteMessage>
      <RegisteredHomeInfoDiv>
        <RegisteredHomeInfoDivTitle>내 집 정보</RegisteredHomeInfoDivTitle>
        <TwoInfoDiv>
          <SmallInfoDiv>
            <SmallInfoKey>보증금</SmallInfoKey>
            <SmallInfoValue>500만원</SmallInfoValue>
          </SmallInfoDiv>
          <SmallInfoDiv>
            <SmallInfoKey>월세</SmallInfoKey>
            <SmallInfoValue>50만원</SmallInfoValue>
          </SmallInfoDiv>
        </TwoInfoDiv>
        <TwoInfoDiv>
          <SmallInfoDiv>
            <SmallInfoKey>크기</SmallInfoKey>
            <SmallInfoValue>23㎡</SmallInfoValue>
          </SmallInfoDiv>
          <SmallInfoDiv>
            <SmallInfoKey>평수</SmallInfoKey>
            <SmallInfoValue>7평</SmallInfoValue>
          </SmallInfoDiv>
        </TwoInfoDiv>
        <TwoInfoDiv>
          <SmallInfoDiv>
            <SmallInfoKey>관리비</SmallInfoKey>
            <SmallInfoValue>6만원</SmallInfoValue>
          </SmallInfoDiv>
          <SmallInfoDiv>
            <SmallInfoKey>구조</SmallInfoKey>
            <SmallInfoValue>원룸(오픈형)</SmallInfoValue>
          </SmallInfoDiv>
        </TwoInfoDiv>
      </RegisteredHomeInfoDiv>
      <CompleteButton onClick={handleGoCompleteButtonClick}>
        확인
      </CompleteButton>
    </StepsContainer>
  );
};

export default RegisterComplete;

const StepsContainer = styled.div`
  position: relative;

  background-color: #ffffff;

  display: flex;
  flex-direction: column;
  justify-content: center;
  text-align: center;
  align-items: center;

  width: 100%;

  /* border: 1px solid green;
  box-sizing: border-box; */
`;

const RegisterHomeCompleteMessage = styled.div`
  position: absolute;
  text-align: center;

  font-size: 25px;
  font-weight: 700;

  color: black;

  top: 275px;

  /* border: 1px solid red; */
`;

const RegisteredHomeInfoDiv = styled.div`
  position: absolute;
  width: 284px;

  top: 360px;

  /* border: 1px solid green;
  box-sizing: border-box; */
`;

const RegisteredHomeInfoDivTitle = styled.div`
  width: 100%;
  height: 48px;

  margin-bottom: 41px;

  top: 0px;
  left: 0px;

  font-size: 20px;
  font-weight: 500;

  display: flex;
  align-items: center;

  border-bottom: 1px solid #d7dbde;
`;

const TwoInfoDiv = styled.div`
  width: 100%;

  display: flex;
  justify-content: space-between;
  align-items: center;

  //보려면 이거 필요
  /* border: 1px solid purple;
  box-sizing: border-box; */
`;

const SmallInfoDiv = styled.div`
  position: relative;

  width: 48%;
  height: 26px;

  display: flex;
  align-items: center;

  /* border: 1px solid red;
  box-sizing: border-box; */
`;

const SmallInfoKey = styled.div`
  position: absolute;

  height: 20px;

  font-size: 17px;
  font-weight: 500;

  color: black;

  left: 0px;

  /* border: 1px solid red;
  box-sizing: border-box; */
`;

const SmallInfoValue = styled.div`
  position: absolute;

  height: 20px;

  font-size: 15px;
  font-weight: 500;

  color: #797979;

  text-align: center;
  align-content: center;

  left: 60px;

  /* border: 1px solid red;
  box-sizing: border-box; */
`;

const CompleteButton = styled.button`
  position: absolute;
  width: 350px;
  height: 60px;

  top: 590px;

  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center;

  font-size: 20px;
  font-weight: 500;

  color: #bffa00;

  border-radius: 10px;

  background-color: black;
`;

const RegisterHomeCompleteGif: React.FC = () => {
  const [showGif, setShowGif] = useState(true);

  useEffect(() => {
    // 3초 후에 GIF를 멈추도록 처리
    const timer = setTimeout(() => {
      setShowGif(false);
    }, 2200); // 3초

    // 컴포넌트가 언마운트될 때 타이머를 정리
    return () => clearTimeout(timer);
  }, []);

  return (
    <>
      <img
        src="/img/register/newHome/registerComplete/registerHomeComplete.png"
        alt="registerHomeCompletePng"
        width={162}
        height={154}
        style={{ top: "110epx", position: "absolute" }}
      />
      {showGif && (
        <img
          src="/img/register/newHome/registerComplete/registerHomeComplete.gif"
          alt="registerHomeCompleteGif"
          width={162}
          height={154}
          style={{ top: "110px", position: "absolute" }}
        />
      )}
    </>
  );
};

{
  /* <>
    {showGif ? (
      <img
        src="/img/register/newHome/registerComplete/registerHomeComplete.gif"
        alt="registerHomeCompleteGif"
        width={162}
        height={154}
        style={{ marginTop: "110px" }}
      />
    ) : (
      <img
        src="/img/register/newHome/registerComplete/registerHomeComplete.png"
        alt="registerHomeCompletePng"
        width={162}
        height={154}
        style={{ marginTop: "110px" }}
      />
    )}
    </> */
}

이런 형식으로 보내야했다.

 

이렇게 성공 response를 받았다.

 

진짜 오래걸렸지만 성공하니 아주 뿌듯뿌듯!!!!!!!

 

[참고]

https://velog.io/@kyungjune/axios%EB%A1%9C-image-%EC%97%85%EB%A1%9C%EB%93%9C%ED%95%98%EA%B8%B0

 

axios로 image 업로드하기

진행중인 프로젝트에서 프로필 사진을 업로드해야했었고, 백엔드쪽에서 이미지파일은 multipart/form-data로 해주세요~ 라는 요청이있었다.input 타입을 file로 지정하면 파일을 가져올수있는 형태의 i

velog.io

https://kyung-a.tistory.com/33

 

로그인 시 header에 Authorization이 안 뜨는 현상 | React, JWT, Spring Boot

오늘은 이번 사이드 프로젝트에서 동료랑 오지게 삽질한........ 에러에 대해 기록하려고 합니다 문제를 궁극적으로 해결했다기 보다는 결국 조금 수정해서 다른 방식으로 우회(?) 했습니다 혹시.

kyung-a.tistory.com

https://velog.io/@cloud_oort/Next.js-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EA%B5%AC%ED%98%84-Silent-refresh

 

[Next.js] 로그인 구현 (Silent refresh)

회원가입 이후 로그인과 로그인 유지를 구현하고자 한다. 로그인 유지 방법으로 JWT을 사용했다.

velog.io

https://joylee-developer.tistory.com/187

 

[Javascript] localStorage 사용하기

LocalStorage 브라우저에 자료를 저장할 수 있는 저장소이다. cookie와의 차이점 Cookie LocalStorage 공통점 브라우저에 자료를 저장하는 저장소 키-값 형태의 자료를 저장한다 차이점 만료 기한이 있다(

joylee-developer.tistory.com