From 2bacf088e87eb4c0b7f809c162738b34084c2264 Mon Sep 17 00:00:00 2001 From: jyeon03 Date: Wed, 30 Jul 2025 19:10:48 +0900 Subject: [PATCH 1/3] =?UTF-8?q?Refactor:=20useWindowSize=EB=A1=9C=20?= =?UTF-8?q?=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/WindowSizeExample.jsx | 22 ++-------------------- src/hooks/useWindowSize.js | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/components/WindowSizeExample.jsx b/src/components/WindowSizeExample.jsx index 8a4c768..6b142fe 100644 --- a/src/components/WindowSizeExample.jsx +++ b/src/components/WindowSizeExample.jsx @@ -1,26 +1,8 @@ -import { useEffect, useState } from "react"; +import { useWindowSize } from "../hooks/useWindowSize"; export const WindowSizeExample = () => { // 실습 1. 하단 코드를 useWindowSize (커스텀 훅으로 바꿔주세요!) - const [windowSize, setWindowSize] = useState({ - width: window.innerWidth, - height: window.innerHeight, - }); - - useEffect(() => { - const handleResize = () => { - setWindowSize({ - width: window.innerWidth, - height: window.innerHeight, - }); - }; - - window.addEventListener("resize", handleResize); - - return () => { - window.removeEventListener("resize", handleResize); - }; - }, []); + const { windowSize } = useWindowSize(); return (
diff --git a/src/hooks/useWindowSize.js b/src/hooks/useWindowSize.js index 28d9f7c..9b26359 100644 --- a/src/hooks/useWindowSize.js +++ b/src/hooks/useWindowSize.js @@ -1 +1,27 @@ +import { useEffect, useState } from "react"; + + // 커스텀훅 코드를 작성해보세요! +export const useWindowSize = () => { + const [windowSize, setWindowSize] = useState({ + width: window.innerWidth, + height: window.innerHeight, + }); + + useEffect(() => { + const handleResize = () => { + setWindowSize({ + width: window.innerWidth, + height: window.innerHeight, + }); + }; + + window.addEventListener("resize", handleResize); + + return () => { + window.removeEventListener("resize", handleResize); + }; + }, []); + + return { windowSize }; +}; From a37c87bcc3edea1f045edc511ffcd4ce2651e3a3 Mon Sep 17 00:00:00 2001 From: jyeon03 Date: Wed, 30 Jul 2025 19:19:27 +0900 Subject: [PATCH 2/3] =?UTF-8?q?Refactor:=20useCountdown,=20calculateTime?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/CountdownExample.jsx | 27 ++------------------------- src/hooks/useCountdown.js | 12 ++++++++++++ src/utils/calculateTime.js | 14 ++++++++++++++ 3 files changed, 28 insertions(+), 25 deletions(-) create mode 100644 src/utils/calculateTime.js diff --git a/src/components/CountdownExample.jsx b/src/components/CountdownExample.jsx index e057f19..85228aa 100644 --- a/src/components/CountdownExample.jsx +++ b/src/components/CountdownExample.jsx @@ -1,31 +1,8 @@ -import { useState, useEffect } from "react"; +import { useCountdown } from "../hooks/useCountdown"; export const CountdownExample = () => { const targetDate = new Date("2025-08-25T00:00:00"); - - const calculateTimeLeft = (targetDate) => { - const difference = targetDate.getTime() - new Date().getTime(); - - if (difference <= 0) { - return { days: 0, hours: 0, minutes: 0, seconds: 0 }; - } - - const days = Math.floor(difference / (1000 * 60 * 60 * 24)); - const hours = Math.floor((difference / (1000 * 60 * 60)) % 24); - const minutes = Math.floor((difference / (1000 * 60)) % 60); - const seconds = Math.floor((difference / 1000) % 60); - - return { days, hours, minutes, seconds }; - }; - const [timeLeft, setTimeLeft] = useState(() => calculateTimeLeft(targetDate)); - - useEffect(() => { - const timer = setInterval(() => { - setTimeLeft(calculateTimeLeft(targetDate)); - }, 1000); - - return () => clearInterval(timer); - }, [targetDate]); + const timeLeft = useCountdown(targetDate); return (
diff --git a/src/hooks/useCountdown.js b/src/hooks/useCountdown.js index 19c04c3..156f352 100644 --- a/src/hooks/useCountdown.js +++ b/src/hooks/useCountdown.js @@ -1,3 +1,15 @@ +import { useEffect, useState } from "react"; +import { calculateTimeLeft } from "../utils/calculateTime"; + export const useCountdown = (targetDate) => { + const [timeLeft, setTimeLeft] = useState(() => calculateTimeLeft(targetDate)); + + useEffect(() => { + const timer = setInterval(() => { + setTimeLeft(calculateTimeLeft(targetDate)); + }, 1000); + + return () => clearInterval(timer); + }, [targetDate]); return timeLeft; }; diff --git a/src/utils/calculateTime.js b/src/utils/calculateTime.js new file mode 100644 index 0000000..c7caa7f --- /dev/null +++ b/src/utils/calculateTime.js @@ -0,0 +1,14 @@ +export const calculateTimeLeft = (targetDate) => { + const difference = targetDate.getTime() - new Date().getTime(); + + if (difference <= 0) { + return { days: 0, hours: 0, minutes: 0, seconds: 0 }; + } + + const days = Math.floor(difference / (1000 * 60 * 60 * 24)); + const hours = Math.floor((difference / (1000 * 60 * 60)) % 24); + const minutes = Math.floor((difference / (1000 * 60)) % 60); + const seconds = Math.floor((difference / 1000) % 60); + + return { days, hours, minutes, seconds }; +}; From 4eba835d424f405f238df566f33c38ad9946e966 Mon Sep 17 00:00:00 2001 From: jyeon03 Date: Wed, 30 Jul 2025 19:39:12 +0900 Subject: [PATCH 3/3] =?UTF-8?q?Feature:=20useMyName=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/YourOwnHookPage.jsx | 10 +++++++--- src/hooks/useConfetti.js | 13 ++++++++++++- src/hooks/useMyName.js | 23 +++++++++++++++++++++++ src/hooks/useSomething.js | 5 ----- 4 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 src/hooks/useMyName.js delete mode 100644 src/hooks/useSomething.js diff --git a/src/components/YourOwnHookPage.jsx b/src/components/YourOwnHookPage.jsx index ee5502f..424e64f 100644 --- a/src/components/YourOwnHookPage.jsx +++ b/src/components/YourOwnHookPage.jsx @@ -1,11 +1,15 @@ -import { useSomething } from "../hooks/useSomething"; +import { useName } from "../hooks/useMyName"; export const YourOwnHookPage = () => { - // const { something... } = useSomething(); - // 하단 UI에 자유롭게 위에서 받아온 값들을 바인딩 해보세요~ + const { name, changeName } = useName(); + return (

useSomething 실습

+

{name}

+
); }; diff --git a/src/hooks/useConfetti.js b/src/hooks/useConfetti.js index 662f311..ecf9592 100644 --- a/src/hooks/useConfetti.js +++ b/src/hooks/useConfetti.js @@ -8,5 +8,16 @@ export const useConfetti = () => { origin: { y: 0.6 }, }); }; - return { fire }; + + const fire2 = () => { + confetti({ + particleCount: 100, + spread: 360, + origin: { + x: Math.random(), + y: Math.random() - 0.2, + }, + }); + }; + return { fire, fire2 }; }; diff --git a/src/hooks/useMyName.js b/src/hooks/useMyName.js new file mode 100644 index 0000000..d713221 --- /dev/null +++ b/src/hooks/useMyName.js @@ -0,0 +1,23 @@ +import { useEffect, useState } from "react"; +import { useConfetti } from "./useConfetti"; + +export const useName = () => { + // 여러분의 use{name}을 만들어주세요! + // 정답은 없습니다. 커스텀훅의 필요성을 스스로 느껴보세요. + // 아이디어를 생각하고, 스스로 구현하다가 어려우면 손 들어주세요! + const [name, setName] = useState("아기사자"); + const { fire2 } = useConfetti(); + + const changeName = () => { + setName((prev) => (prev === "아기사자" ? "아기사자 백지연" : "아기사자")); + }; + + useEffect(() => { + fire2(); + }, [name]); + + return { + name, + changeName, + }; +}; diff --git a/src/hooks/useSomething.js b/src/hooks/useSomething.js deleted file mode 100644 index 48815a1..0000000 --- a/src/hooks/useSomething.js +++ /dev/null @@ -1,5 +0,0 @@ -export const useSomething = () => { - // 여러분의 use{Something}을 만들어주세요! - // 정답은 없습니다. 커스텀훅의 필요성을 스스로 느껴보세요. - // 아이디어를 생각하고, 스스로 구현하다가 어려우면 손 들어주세요! -};