본문 바로가기
Study/ft_transcendence

[React] 22.07.11 회고록

by jeongwle 2022. 7. 11.
728x90
반응형

후회

바쁘다는 핑계로 리액트로 프로젝트를 하면서 시행착오와 배운 것들을 정리하지 않았다. 프로젝트를 목표한 시간 내에 끝내야 한다는 압박감에 블로그에 정리하는 것은 사치다 라고 자기위로를 하며 하루하루를 보냈다. 프로젝트를 시작하고 매일매일 검색하고 들이받아보면서 지금까지 왔는데 그것들을 다 정리해놓았다면 나중에 조금이라도 도움이 되지 않았을까 하는 후회를 뒤로하고 오늘부터라도 오늘의 시행착오 및 배운 것들을 나열하면서 기록해두자는 생각을 하게 되었다. 그래 오늘부터라도 시작하자.

 

이미지 업로드

리액트로 이미지를 업로드하는 여러 글들을 찾아보았다. 

function PopUpProfile(): JSX.Element {
const [preview, setPreview] = useState(DefltImg);

const previewImg = (
    event: React.ChangeEvent<HTMLInputElement> & { target: HTMLInputElement },
  ) => {
    const { target } = event;
    if (target.files?.length) {
      const fileReader = new FileReader();
      fileReader.readAsDataURL(target.files[0]);
      fileReader.onloadend = () => {
        console.log(fileReader.result);
        if (typeof fileReader.result === "string") {
          setPreview(fileReader.result);
        }
      };
    }
  };
  return (
            <div
            className="img__wrap relative"
            onMouseEnter={handleMouseEnter}
            onMouseLeave={handleMouseLeave}
          >
            {display && (
              <label
                htmlFor="profileImg"
                className="bg-black w-[130px] h-[25px] absolute top-[70px] left-[10px] text-white text-center font-main rounded-full"
                onMouseEnter={handleMouseEnter}
              >
                눌러서 바꿔보세요
              </label>
            )}
            <input
              type="file"
              id="profileImg"
              accept="image/*"
              onChange={(event) => {
                // previewImg(event);
                onFinish(event);
              }}
              className="hidden"
            />
            <div className="img__wrap">
              <img
                alt="profileImg"
                src={`http://localhost:3000/${userInfo.profileImg}`}
                className="rounded-full w-[150px] h-[150px] p-2"
              />
            </div>
  )
 }

코드의 일부분만 담았다. 처음에는 이미지를 바꿀 때 preview를 보여줄 요량으로 블로그에서 보았단 fileReader를 사용하여 이미지를 string url로 바꾸는 것에 성공하였고 그것을 <img> 태그에서 src={preview}이렇게 보여주는 것을 성공하였으나 그러한 구조를 버리고 그냥 다 저장하고 저장한 것을 불러와서 보여주자는 생각을 하게 되었다. 하지만 이 코드를 짜면서 얻은 것이 아예 없는 것은 아니다. 타입스크립트는 정확하게 타입이 무엇이다 라고 좁혀지지 않으면 컴파일이 안된다는 것을 이제서야 깨닫게 되었고 그것들을 이용하여 preview 이미지를 띄우는 데 성공한 것이다. 

 

  const onFinish = async (
    event: React.ChangeEvent<HTMLInputElement> & { target: HTMLInputElement },
  ) => {
    const { target } = event;
    const formData = new FormData();
    const accessToken = getCookie("token");
    if (target.files?.length) {
      formData.append("profile", target.files[0]);
      console.log("this is target ", target.files[0]);
      console.log("this is formdata ", formData.get("profile"));
      console.log(formData);
      await axios({
        url: "http://localhost:3000/user/info",
        method: "patch",
        headers: {
          Authorization: `Bearer ${accessToken}`,
          "Content-Type": "multipart/form-data", // Content-Type을 반드시 이렇게 하여야 한다. 라고 한다.
        },
        data: formData,
      })
        .then(() => {
          console.log("프로필 변경 완료");
          console.log(
            "this is url = ",
            "http://localhost:3000/" + userInfo.profileImg,
          );
          setReq((prev) => prev + 1);
        })
        .catch((err) => {
          console.log(err);
        });
    }
  };

현재는 이런식으로 코드를 고쳤고 console.log는 확인해가면서 시행착오를 거듭했던 모습을 기록해두기 위해 그냥 두었다. 여기서도 고비는 있었다. 프로필 이미지를 바꾸고나서 렌더링을 새로 해주고 바뀐 정보를 불러와서 이미지를 띄워주어야 한다. 여기서 우리는 recoil을 사용하고 있는데 처음에는 selector의 set 함수를 불러와서 사용하려 했으나 자꾸 변수를 요구했고 변수를 하나로 고정하자 한번 렌더링 후 다음에 또 렌더링이 필요한 시점에 렌더링이 되지 않는 문제를 겪었고, 오래도록 고민한 결과 그냥 구독하고 있는 atom의 set함수를 불러와서 prev => prev + 1을 해주면 되지 않을까 하는 생각을 하게 되었다. 다행히 생각한대로 잘 렌더링 되어서 이미지 업로드는 어느정도 성과를 볼 수 있었다. 성공이라 단정 짓지 못하는 이유는 처음하는 리액트이고 어디서 오류가 날 수 있지 않을까 하는 생각에 그렇다.

 

react-cookie

쿠키에서 access token을 가져오기 위해 react-cookie를 설치하였다. 이번에도 블로그를 검색하면서 적용해보았다.

import React, { Suspense } from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import { RecoilRoot } from "recoil";
import PageLoading from "./components/PageLoading";
import { CookiesProvider } from "react-cookie";

const root = ReactDOM.createRoot(
  document.getElementById("root") as HTMLElement,
);
root.render(
  // <React.StrictMode>
  <RecoilRoot>
    <CookiesProvider>
      <Suspense fallback={<PageLoading />}>
        <App />
      </Suspense>
    </CookiesProvider>
  </RecoilRoot>,
  // </React.StrictMode>,
);

현재 recoil을 사용해서 <RecoilRoot>로 <App />을 감싸놓았고, selector에서 api를 요청하는 시간을 기다리기 위해 <Suspense fallback={<PageLoading />}> 으로 또 감싸놓았다. 여기에 이어 이번엔 cookie를 가져오기 위해서는 <CookiesProvider>로 감싸주어야 한다고 해서 감싸주었다. 감싸주어야 쓸 수 있다고 해서 감싸주었을 뿐 정확한 이유는 모른다.

 

import { Cookies } from "react-cookie";

const cookies = new Cookies();

export const setCookie = (name: string, value: string, { ...options }) => {
  return cookies.set(name, value, { ...options });
};

export const getCookie = (name: string) => {
  return cookies.get(name);
};

쿠키를 사용하는 법도 검색한 블로그에서 발견한 것을 그대로 사용하였다. 간단하게 setCookie와 getCookie만 정의해놓고 사용하고 있다.

 

앞으로 해야할 일들이 태산처럼 많이 쌓여있다. 하지만 하나씩 천천히 매일 해오던 것처럼 또 머리를 박고 부딪히고 하면서 해결해 나갈 예정이다. 목표한 시간은 다가오고 있지만 그래도 오늘처럼 매일매일 회고록을 남기자. 이렇게라도 기록해두면 나중에 한번쯤은 들여다보지 않을까? 하는 생각을 하며 오늘의 글을 마친다.

728x90
반응형

댓글