React 45장 - TSX로 리팩토링하기 (2)
포스트
취소

React 45장 - TSX로 리팩토링하기 (2)

React

TO-Do List 링크

리팩토링

너무 오랜만에 남기는 거라 작성해야 될 게 많이 남았지만 현재 작성하고 있는 부분까지만 작성해본다.

useQuery 사용하기

Login.tsx

  1. npm install react-query를 설치한다.
    1. 타입스크립트의 타입을 위해 npm install @types/react-query 또한 설치한다.
  2. 컴포넌트에서 Query 사용을 위해 최상위 컴포넌트인 App.tsx에서 QueryClient를 선언 후 컴포넌트를 감싸준다.

    1
    2
    3
    
    const queryClient = new QueryClient();
    
    return <QueryClientProvider client={queryClient}></QueryClientProvider>;
    
  3. 쿼리를 추적하기 위해 ReactQueryDevtools 또한 하단에 작성한다.

    1
    2
    3
    4
    5
    
    import { ReactQueryDevtools } from "react-query/devtools";
    
    return(
    <ReactQueryDevtools></ReactQueryDevtools>;
    )
    
  4. 기존에 axios를 사용하여 작성된 코드를 useQuery로 변경한다.

    // 기존 코드
    const loginApi = () => {
    axios.get<LoginUser[]>("http://localhost:4000/login").then((res) => {
        const matchedUser = res.data.find(
        (user) => user.id === id && user.pass === pw
        );
        if (matchedUser) {
        // 로그인 성공 처리
        setLoginValue(!loginValue);
        setMessage(true);
        } else {
        // 로그인 실패 처리
        setMessage(false);
        }
    });}
    
    async function login() {
    
    const res = await axios.get("http://localhost:4000/login");
    return res;
    }
    
    const { data, isLoading, isError, error } = useQuery("get", () => login(), {
        refetchOnWindowFocus: false,
    });
    
    const loginApi = async () => {
        const response = await axios.get("http://localhost:4000/login");
        const matchedUser = response.data.find(
            (user: LoginUser) => user.id === id && user.pw === pw
        );
        if (matchedUser) {
        // 로그인 성공 처리
        setLoginValue(!loginValue);
        setMessage(true);
        } else {
        // 로그인 실패 처리
        setMessage(false);
        }
    };
    

SignPage.tsx

꽤나 애먹었던 SignPage 리팩토링… api부터 error처리까지, 그리 어렵지 않다고 생각하던 게 정말 오래 걸렸다.

  1. post 요청을 보낼 함수를 작성한다.

    1. 처음 작성한 코드는 post를 요청하는 함수에서 에러를 처리하려 했으나, api에서 요청을 보낼 때 유효성 검사를 진행 후 상태코드를 전달하는 방식으로 처리하면 된다.
    2. 이렇게 작성하면 signIn함수의 조건문을 전부 지워줘도 된다.
    3. api 코드에 작성된 유효성 검사가 진행되지 않았는데 endpoint가 같아서 작동되지 않아서 login 엔드포인트를 공유하던 것을 signin으로 바꿔줬다.
    1
    2
    3
    4
    5
    6
    7
    
    async function signIn(idPw: LoginUser) {
      const res = await axios.post("http://localhost:4000/signin", idPw);
      if (res.data === "id나 pw가 없습니다.") setIdError(res.data);
      else if (res.data === "중복되는 아이디입니다.") setIdError(res.data);
      else setIdError("");
      return res;
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    app.post("/signin", (req, res) => {
      const { id, pw } = req.body;
      if (!id || !pw) {
        console.log("id나 pw가 없습니다.");
        return res.status(400).json({ message: "id나 pw가 없습니다." });
      }
      const alreadyId = login.find((user) => user.id === id);
      console.log(login.find((user) => user.id === id));
      if (alreadyId !== undefined) {
        console.log("중복되는 아이디입니다.");
        return res.status(400).json({ message: "중복되는 아이디입니다." });
      }
      login.push({ id, pw });
      console.log(login);
      return res.json(login);
    });
    
  2. 회원가입에 대한 처리는 useMutation을 사용하여 처리했다.

    1. 처음엔 onError와 onSuccess를 활용하지 않고 state를 활용하는 방식으로 에러를 처리하는 삽질도 오래 했다.
    2. 다음엔 내장 함수를 적극 활용하도록 하자.
    3. 타입에러도 많이 떴는데 err의 response의 에러 메시지를 가져오고 싶었으나 타입 에러가 많이 발생했다.
      1. AxiosError 타입이 있으니 이를 지정해주고, 데이터를 받는 비동기 함수의 unknown 타입이므로 optional을 사용해준다.
    1
    2
    3
    4
    5
    6
    7
    
    const postSignIn = useMutation((idPw: LoginUser) => signIn(idPw), {
      onError: (err: AxiosError<ResponseData>) =>
        alert(err.response?.data?.message),
      onSuccess: () => {
        alert("회원 가입에 성공했습니다.");
      },
    });
    
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.