โœ๐Ÿป [Code Camp_TIL] 26์ผ์ฐจ: ๊ตฌ์กฐ๋ถ„ํ•ดํ• ๋‹น, rest ํŒŒ๋ผ๋ฏธํ„ฐ, custom hooks, ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ Generic

code_Jยท2023๋…„ 4์›” 23์ผ
0

TIL

๋ชฉ๋ก ๋ณด๊ธฐ
32/41
post-thumbnail

๊ตฌ์กฐ๋ถ„ํ•ดํ• ๋‹น(=๋น„๊ตฌ์กฐํ™”ํ• ๋‹น)


๊ตฌ์กฐ๋ถ„ํ•ดํ• ๋‹น(๋น„๊ตฌ์กฐํ™”ํ• ๋‹น)์ด๋ž€ ๋ณ€์ˆ˜๋ฅผ ํ•œ๋ฒˆ์— ๋ชจ๋‘ ์„ ์–ธํ•˜๊ณ  ํ• ๋‹นํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.

๊ฐ์ฒด์˜ ๊ตฌ์กฐ๋ถ„ํ•ดํ• ๋‹น

const child = {
	name: "์ฒ ์ˆ˜",
  	age: 13,
  school: "๋‹ค๋žŒ์ฅ์ดˆ๋“ฑํ•™๊ต"
}

์œ„์˜ ์ฝ”๋“œ๋Š” ๊ฐ์ฒด์˜ ๊ตฌ์กฐ๋ฅผ ๋ถ„ํ•ดํ•ด์„œ ๋ณ€์ˆ˜๋ฅผ ํ• ๋‹นํ•˜๋Š” ๊ตฌ์กฐ๋ถ„ํ•ดํ• ๋‹น ๋ฐฉ์‹์ด๋‹ค.


๊ฐ์ฒด์˜ value ๊ฐ’์„ ๊ฐ๊ฐ ์ƒˆ๋กœ์šด ๋ณ€์ˆ˜์— ํ• ๋‹นํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•˜๋‚˜์”ฉ ์„ ์–ธํ•˜๊ณ  ํ• ๋‹นํ•ด์•ผ ํ–ˆ๋‹ค.

const name = child.name
const age = child.age
const school = child.school

ํ•˜์ง€๋งŒ ๋„ˆ๋ฌด ๊ธธ๊ณ , ๋ฒˆ๊ฑฐ๋กœ์›Œ ๋ณด์ธ๋‹ค. ๋”ฐ๋ผ์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ถ•์•ฝ(๊ตฌ์กฐ๋ถ„ํ•ดํ• ๋‹น)ํ•  ์ˆ˜ ์žˆ๋‹ค.

const { name, age, school } = child

๊ฐ์ฒด์˜ ๊ตฌ์กฐ๋ถ„ํ•ด ํ• ๋‹น์€ ์„ ์–ธ๋ถ€์— ์ค‘๊ด„ํ˜ธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ, ๊ฐ์ฒด์˜ key๊ฐ’์„ ๋ณ€์ˆ˜๋ช…์œผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค. ๋ณ€์ˆ˜๋ช…์„ ๋‹ค๋ฅธ ์ด๋ฆ„์œผ๋กœ ์ง€์ •ํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค.


useQuery๋„ ๊ตฌ์กฐ๋ถ„ํ•ดํ• ๋‹น์„ ์‚ฌ์šฉ

์šฐ๋ฆฌ๋Š” useQuery๋ฅผ ์“ธ ๋•Œ์—๋„ ๊ฐ์ฒด๋ฅผ ๊ตฌ์กฐ๋ถ„ํ•ดํ• ๋‹นํ•˜๊ณ  ์žˆ์—ˆ๋‹ค!

const { data, loading } = useQuery(FETCH_BOARDS)

์œ„์—์„œ return ๊ฐ’์€ data์™€ loading์ด ๋œ๋‹ค. const aaa = useQuery(FETCH_BOARDS) ๋กœ ๋ฐ›์•„์™€ aaa.data, aaa.loading ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.


๋ฐฐ์—ด์˜ ๊ตฌ์กฐ๋ถ„ํ•ดํ• ๋‹น

๋ฐฐ์—ด๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๊ตฌ์กฐ๋ถ„ํ•ดํ• ๋‹น์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

const classmates = ["์ฒ ์ˆ˜","์˜ํฌ","ํ›ˆ์ด"]

์ด์ „๊นŒ์ง€๋Š” ๋ฐฐ์—ด์˜ ์›์†Œ๋ฅผ ๊ฐ๊ฐ ๋‹ค๋ฅธ ๋ณ€์ˆ˜์— ํ• ๋‹นํ• ๋ ค๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•ด์•ผ๋งŒ ํ–ˆ๋‹ค.

const child1 = classmates[0]

const child2 = classmates[1]

const child3 = classmates[2]

ํ•˜์ง€๋งŒ ๊ตฌ์กฐ๋ถ„ํ•ดํ• ๋‹น์„ ์‚ฌ์šฉํ•˜๋ฉด ํ›จ์”ฌ ๊ฐ„๋‹จํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค.

const [child1, child2, child3] = classmates

๋ฐฐ์—ด์˜ ๊ตฌ์กฐ๋ถ„ํ•ด ํ• ๋‹น์€ ์„ ์–ธ๋ถ€์— ๋Œ€๊ด„ํ˜ธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ, ๊ฐ์ฒด์˜ ๊ตฌ์กฐ๋ถ„ํ•ดํ• ๋‹น๊ณผ ๋‹ค๋ฅด๊ฒŒ ๋ณ€์ˆ˜๋ช…์€ ๋งˆ์Œ๋Œ€๋กœ ์ •ํ•ด๋„ ๋œ๋‹ค. ๋‹ค๋งŒ ๋ฐฐ์—ด์˜ ์›์†Œ ํ• ๋‹น์€ ์ธ๋ฑ์Šค์˜ ์ˆœ์„œ๋Œ€๋กœ ๋“ค์–ด๊ฐ„๋‹ค.


useState์—๋„ ๊ตฌ์กฐ๋ถ„ํ•ดํ• ๋‹น ์‚ฌ์šฉ

์šฐ๋ฆฌ๋Š” useState๋ฅผ ์“ธ ๋•Œ์—๋„ ๋ฐฐ์—ด์˜ ๊ตฌ์กฐ๋ถ„ํ•ดํ• ๋‹น์„ ์‚ฌ์šฉํ–ˆ๋‹ค.

const [state,setState] = useState("")

const qqq = useState(โ€โ€) ์˜ ๋ฆฌํ„ด๊ฐ’์ด ๋ฐฐ์—ด์ด๋ฏ€๋กœ const state = qqq[0], const setCounter = qqq[1]๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.



REST ํŒŒ๋ผ๋ฏธํ„ฐ

์šฐ๋ฆฌ๊ฐ€ ๊ฐ์ฒด์—์„œ ์ง€์šฐ๊ณ  ์‹ถ์€ ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ? delete๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.

const child = {
	name: "์ฒ ์ˆ˜",
  	age: 13,
  school: "๋‹ค๋žŒ์ฅ์ดˆ๋“ฑํ•™๊ต",
  hobby: "์ถ•๊ตฌ",
  ํ‚ค: 150
}

์œ„์—์„œ name๊ณผ school์„ ์ง€์šฐ๊ณ  ์‹ถ์œผ๋ฉด, delete child.name, delete child.school์„ ํ•˜๋ฉด ๋œ๋‹ค.

ํ•˜์ง€๋งŒ ์›๋ณธ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ”๋กœ ์‚ญ์ œํ•˜๋Š” ๊ฒƒ์€ ์ถ”์ฒœํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์•„๋‹ˆ๋‹ค. ์›๋ณธ์ด ์–ด๋””์—์„œ ์–ด๋–ป๊ฒŒ ์“ฐ์ด๊ณ  ์žˆ๋Š”์ง€ ๋ชจ๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ์›๋ณธ์„ ๋ฐ”๋กœ ์ˆ˜์ •ํ–ˆ๋‹ค๊ฐ€ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

๋”ฐ๋ผ์„œ delete๋ณด๋‹ค๋Š” rest ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ด์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. rest ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ๊ตฌ์กฐ๋ถ„ํ•ดํ• ๋‹น๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•œ๋‹ค.

const { name, school, ...rest} = child

์œ„์™€ ๊ฐ™์ด ์ ์œผ๋ฉด ...rest์—๋Š” name๊ณผ school์„ ์ œ์™ธํ•œ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด๊ฐ€๊ฒŒ ๋œ๋‹ค.

*์—ฌ๊ธฐ์„œ rest ๋ถ€๋ถ„์€ rest๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•ด๋„ ์ข‹๋‹ค. ๊ด€๋ก€์ƒ rest๋ผ๊ณ  ์“ฐ๊ณค ํ•œ๋‹ค.


Custom Hooks

custom hook์ด๋ž€ ๊ฐœ๋ฐœ์ž ์Šค์Šค๋กœ ์ปค์Šคํ…€ํ•œ hook์„ ๋œปํ•œ๋‹ค.

custom hook๋„ ํ•จ์ˆ˜์ธ๋ฐ, ์ผ๋ฐ˜ํ•จ์ˆ˜์™€๋Š” ์–ด๋–ค ์ฐจ์ด์ ์ด ์žˆ๊ณ , ๊ตณ์ด custom hook์„ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๊ฐ€ ๋ญ˜๊นŒ?

์‚ฌ์‹ค ๋ณ„ ์ฐจ์ด๋Š” ์—†์ง€๋งŒ, ๋‚ด๋ถ€์—์„œ useState์™€ ๊ฐ™์€ hook์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด custom hook์ด๋ผ๊ณ  ํ•œ๋‹ค.

custom hook์„ ์‚ฌ์šฉํ•˜๋ฉด ํ•จ์ˆ˜ ๋„ค์ด๋ฐ์— use๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค!

UseAuth ํ•จ์ˆ˜ ๋งŒ๋“ค๊ธฐ

๊ธฐ์กด์— ๋งŒ๋“ค์–ด๋†จ๋˜ withAuth ํŒŒ์ผ์„ ๊ฐ€์ ธ์™€์„œ useAuth ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด๋ดค๋‹ค.

import { useAuth } from "../../../src/components/commons/hooks/useAuth";

export default function CustomHooksUseAuthPage(): JSX.Element {
  useAuth();

  return <div>ํ”„๋กœํ•„ ํŽ˜์ด์ง€์ž…๋‹ˆ๋‹ค.</div>;
}

#useAuth ํŒŒ์ผ

import { useRouter } from "next/router";
import { useEffect } from "react";

// useAuth ์ด๋ฆ„ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ!
export const useAuth = (): void => {
  const router = useRouter();

  // useEffect hooks๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— custom hooks๋‹ค.
  useEffect(() => {
    if (localStorage.getItem("accessToken") === null) {
      alert("๋กœ๊ทธ์ธ ํ›„ ์ด์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค!");
      void router.push("/section23/23-05-login-check-hoc");
    }
  }, []);
};

ํŽ˜์ด์ง€๊ฐ€ ์‹คํ–‰๋˜๋ฉด, useAuth()๊ฐ€ ์‹คํ–‰๋˜์–ด ํ† ํฐ์„ ํ™•์ธ ํ›„ ํ† ํฐ์ด ์กด์žฌํ•œ๋‹ค๋ฉด ํ”„๋กœํ•„ ํŽ˜์ด์ง€๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์ž‘๋™ํ•˜๊ณ , ๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋ฉด ๋กœ๊ทธ์ธ ํ›„์— ์ด์šฉํ•˜๋„๋ก ๊ฒฝ๊ณ ์ฐฝ์„ ๋„์šธ ๊ฒƒ์ด๋‹ค.


ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ Generic


primitive type: ๋ฌธ์ž, ์ˆซ์ž, boolean

const getPrimitive = (arg1: string, arg2: number, arg3: boolean): [boolean, number, string] => {
  return [arg3, arg2, arg1];
};

const result1 = getPrimitive("์ฒ ์ˆ˜", 123, true);

any type

any type์€ ๊ทธ๋ƒฅ javascript์™€ ๊ฐ™๋‹ค. ์–ด๋–ค ํƒ€์ž…์ด ์ž…๋ ฅ๋˜๋”๋ผ๋„ ์ „๋ถ€ ํ—ˆ์šฉํ•œ๋‹ค.

const getAny = (arg1: any, arg2: any, arg3: any): [any, any, any] => {
  console.log(arg1 * 1000);
  return [arg3, arg2, arg1];
};

const result2 = getAny("์ฒ ์ˆ˜", 123, true);

unknown type

any์ฒ˜๋Ÿผ ๋ญ˜ ๋„ฃ์–ด๋„ ์ƒ๊ด€์—†์ง€๋งŒ, ๊ทธ๊ฒƒ์„ ์‹คํ–‰ํ•  ๋•Œ์—๋Š” ์–ด๋–ค ํƒ€์ž…์ผ ๋•Œ ์‹คํ–‰ํ• ์ง€ ์กฐ๊ฑด์„ ๋‹ฌ์•„์ค˜์•ผ ํ•œ๋‹ค. ํƒ€์ž…์ด ์ง€์ •๋˜์ง€ ์•Š์•˜์œผ๋ฏ€๋กœ ์—ฐ์‚ฐ์— ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Œ์„ ๊ฒฝ๊ณ ํ•œ๋‹ค.

const getUnknown = (arg1: unknown, arg2: unknown, arg3: unknown): [unknown, unknown, unknown] => {
  if (typeof arg1 === "number") {
    console.log(arg1 * 1000);
  } 

  return [arg3, arg2, arg1];
};

const result3 = getUnknown("์ฒ ์ˆ˜", 123, true);
const result33 = result3[0] * 10; 
// alert! Object is of type 'unknown'.

generic type

์ธ์ž์— ๋“ค์–ด์˜ค๋Š” ๊ฐ’์— ๋”ฐ๋ผ ํƒ€์ž…์ด ๋ฐ˜ํ™˜๋œ๋‹ค.

function getGeneric4<Mytype1, Mytype2, Mytype3>(arg1: Mytype1, arg2: Mytype2, arg3: Mytype3): [Mytype3, Mytype2, Mytype1] {
  return [arg3, arg2, arg1];
}

const result4 = getGeneric4("์ฒ ์ˆ˜", 123, true);
const result44 = result4[0] * 10;

arg1์€ string ํƒ€์ž…์œผ๋กœ, arg2๋Š” number ํƒ€์ž…์œผ๋กœ, arg3๋Š” boolean ํƒ€์ž…์ด ๋œ๋‹ค.

MyType ๋ถ€๋ถ„์€ ํ•จ์ˆ˜์ฒ˜๋Ÿผ ์‚ฌ์šฉ์ž๊ฐ€ ์›ํ•˜๋Š” ์ด๋ฆ„์„ ์ง€์ •ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค. ํ†ต์ƒ์ ์œผ๋กœ T, U, V ๋“ฑ ๊ฐ„๋‹จํ•œ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•œ๋‹ค.


Generic ํƒ€์ž… ์‹ค๋ฌด ํ™œ์šฉ(HOC)

Generic ํƒ€์ž…์€ useQuery, useMutation์ฒ˜๋Ÿผ ๋‚ด๊ฐ€ ๋งŒ๋“  ๊ธฐ๋Šฅ์„ ๋‹ค๋ฅธ ์‚ฌ๋žŒ์—๊ฒŒ ์ œ๊ณตํ•˜๋Š” ๊ฒฝ์šฐ ์‚ฌ์šฉํ•œ๋‹ค. ๋“ค์–ด์˜ค๋Š” ๊ฐ’์˜ ํƒ€์ž…์— ๋”ฐ๋ผ ๋ฐ˜ํ™˜๋˜๋Š” ๊ฐ’์ด๋‚˜ ์ปดํฌ๋„ŒํŠธ์˜ ํƒ€์ž…์ด ๊ฒฐ์ •๋˜๋„๋ก ํ•œ๋‹ค.

import { useRouter } from "next/router";
import type { ReactElement } from "react";
import { useEffect } from "react";

export const ๋กœ๊ทธ์ธ์ฒดํฌ =
  (์ปดํฌ๋„ŒํŠธ: () => JSX.Element) =>
  <P extends Record<string, unknown>>(ํ”„๋กญ์Šค: P): ReactElement<P> => {
    // props์— ๋ฐ˜๋“œ์‹œ ๊ฐ์ฒด๊ฐ€ ๋“ค์–ด๊ฐ€์•ผ ์Šคํ”„๋ ˆ๋“œ ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, extends๋ฅผ ์‚ฌ์šฉํ•ด์„œ P๋ผ๋Š” Generic ํƒ€์ž…์ด ๊ฐ์ฒด๋ผ๋Š” ์‚ฌ์‹ค์„ ๋ช…์‹œ
    // *JSX.Element ๋Œ€์‹  ReactElement๋ฅผ ์“ฐ๋Š” ์ด์œ ?
    const router = useRouter();

    useEffect(() => {
      if (localStorage.getItem("accessToken") === null) {
        alert("๋กœ๊ทธ์ธ ํ›„ ์ด์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค!");
        void router.push("/section23/23-05-login-check-hoc");
      }
    }, []);

    return <์ปดํฌ๋„ŒํŠธ {...ํ”„๋กญ์Šค} />;
  };

*JSX.Element ํƒ€์ž… ๋Œ€์‹  ReactElement ์“ฐ๋Š” ์ด์œ ?

ReactElement๋Š” JSX.Element์™€ props์˜ ํƒ€์ž…๊นŒ์ง€ ๋‚˜ํƒ€๋‚ด์ค€๋‹ค.

profile
Web FE ๊ฐœ๋ฐœ์ž ์ทจ์ค€์ƒ

0๊ฐœ์˜ ๋Œ“๊ธ€