[TIL] ๋น๋๊ธฐ ํจ์๋ก๋ถํฐ ๋ฐ์์ค๋ data์ ์ ๋ค๋ฆญ ์ฌ์ฉํ๊ธฐ
๐ก TIL 20230914 - ๋น๋๊ธฐ ํจ์๋ก๋ถํฐ ๋ฐ์์ค๋ data์ ์ ๋ค๋ฆญ ์ฌ์ฉํ๊ธฐ
๋น๋๊ธฐ ํจ์๋ก๋ถํฐ ๋ฐ์์ค๋ data์ ํ์ ์๋ฌ ๋ฐ์
useMutation.tsx์์ useMutation ํ ์ ํตํด ๋ฐ์์ค๋ ๋ฐ์ดํฐ์ ํ์์ ์๋์ ๊ฐ์ด ์ง์ ํด๋์๋ค.
// src/hooks/useMutation.tsx
interface UseMutationState<T> {
loading: boolean;
data?: object;
error?: object;
}
// src/components/Auth/Auth.tsx
// ์๋ต
return (
// ... ์ค๊ฐ ์๋ต
{data?.ok ? null : (
<form onSubmit={handleSubmit(onValid)} className="flex flex-col mt-8">
<div className="mt-1">
{method === "email" ? (
<>
๊ทธ๋ฌ๋๋ ์์ data?.ok ๋ถ๋ถ์์ 'Property 'ok' does not exist on type 'object'. ts(2339)' ํ์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
useMutation์ ํตํด ๋ฐ์์ค๋ data๋ ๋น๋๊ธฐ ํจ์๋ก ๋ฐ์์ค๊ธฐ ๋๋ฌธ์ ์ ์ธ ์์ ์ ๋ฐ์ดํฐ ํ์ ์ ํ๋ณํ๊ธฐ ์ด๋ ต๋ค. ๋ฐ๋ผ์ data๊ฐ ์์ฑ๋๋ ์์ (๋น๋๊ธฐ๋ฅผ ํตํด data๋ฅผ ๋ฐ์์ค๋ ์์ )์ ํ์ ์ ๋ช ์ํด์ฃผ์ด์ผ ํ๋ค. ์ด๋ฅผ ์ํด ์ ๋ค๋ฆญ์ ์ฌ์ฉํด์ ํ์ ์ ์ง์ ํ์๋ค.
์ ๋ค๋ฆญ ํ์ (Generic Type)์ด๋?
์ ์ธ ์์ ์ด ์๋๋ผ ์์ฑ ์์ ์ ํ์ ์ ๋ช ์ํ์ฌ ํ๋์ ํ์ ๋ง์ด ์๋ ๋ค์ํ ํ์ ์ ์ฌ์ฉํ ์ ์๋๋ก ํ๋ ๊ธฐ๋ฒ
- ํ๋ฒ์ ์ ์ธ์ผ๋ก ๋ค์ํ ํ์ ์ ์ฌ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค๋ ์ฅ์ ์ด ์๋ค.
- T๋ ์ ๋ค๋ฆญ์ ์ ์ธํ ๋ ๊ด์ฉ์ ์ผ๋ก ์ฌ์ฉ๋๋ ์๋ณ์๋ก ํ์ ํ๋ผ๋ฏธํฐ(Type parameter)๋ผ ํ๋ค.
- ํจ์์๋ ์ ๋ค๋ฆญ์ ์ฌ์ฉํ ์ ์๋ค. ์ ๋ค๋ฆญ์ ์ฌ์ฉํ๋ฉด ํ๋์ ํ์ ๋ง์ด ์๋ ๋ค์ํ ํ์ ์ ๋งค๊ฐ๋ณ์์ ๋ฆฌํด๊ฐ์ ์ฌ์ฉํ ์ ์๋ค.
useMutation.tsx
import { useState } from "react";
interface UseMutationState<T> {
loading: boolean;
data?: T;
error?: object;
}
type UseMutationResult<T> = [(data: any) => void, UseMutationState<T>];
const useMutation = <T = any>(url: string): UseMutationResult<T> => {
const [state, setState] = useState<UseMutationState<T>>({
loading: false,
data: undefined,
error: undefined,
})
const mutationFn = async (data: any) => {
fetch(url, {
method: "POST",
body: JSON.stringify(data),
})
.then((res) => res.json().catch(() => {}))
.then((data) => setState((prev) => ({ ...prev, data, loading: false })))
.catch((error) => setState((prev) => ({ ...prev, error })))
.finally(() => setState((prev) => ({ ...prev, loading: false })))
};
return [mutationFn, { ...state }];
};
export default useMutation;
- <T = any> : ์ฐ์ useMutation.tsx์์ useMutation์ ์ ๋ค๋ฆญ์ ์ฌ์ฉํด์ ๊ธฐ๋ณธ์ ์ผ๋ก any ํ์ ์ ๊ฐ์ง๋ค๊ณ ์ ์ธํด์ฃผ์๋ค.
- UseMutationResult<T> : ์ด๊ฑธ UseMutationResult๋ก ๋ณด๋ด๊ณ ,
- UseMutationState<T> : UseMutationResult๊ฐ ๋ฐ์ผ๋ฉด UseMutationState์๋ ๋ณด๋ด์ค๋ค.
- data?: T : UseMutationState๊ฐ ๋ฐ์ผ๋ฉด data?: ๋ Tํ์ ์ด๋ผ๊ณ ๋ช ์ํด์ค๋ค.
์ ๋ค๋ฆญ์ ์ฌ์ฉํ Auth.tsx ๊ฒฐ๊ณผ
// components/Auth.tsx
"use client";
import { NextComponentType } from "next";
import { useState } from "react";
import { useForm } from "react-hook-form";
import { useMutation, useIsMobile } from "@/hooks";
import { TabButtons, Button, Input } from "@/components";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faComment } from "@fortawesome/free-solid-svg-icons";
interface AuthForm {
email?: string;
phone?: string;
}
// AuthMutationResult ์ถ๊ฐ
interface AuthMutationResult {
ok: boolean;
}
const Auth: NextComponentType = () => {
// ... ์ค๊ฐ ์๋ต
return (
// ... ์ค๊ฐ ์๋ต
<div className="max-w-2xl mx-auto">
{data?.ok ? null : (
<form onSubmit={handleSubmit(onValid)} className="flex flex-col mt-8">
์์ ๊ฐ์ด data์ ํ์ ์ด AuthMutationResult ๋๋ undefined๋ก ํ์ ์ด ์ง์ ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
์ฐธ๊ณ ์ฌ์ดํธ
๋ ธ๋ง๋ ์ฝ๋ - ์บ๋ฟ๋ง์ผ ํด๋ก ์ฝ๋ฉ
12.7 TypeScript - Generic | PoiemaWeb