๐Ÿฎ ๋ฏธ๋‹ˆ ํ”„๋กœ์ ํŠธ/๐Ÿ… ๋ฝ€๋ชจ๋„๋กœ

๐Ÿ… REACT ๋ฝ€๋ชจ๋„๋กœ ํƒ€์ด๋จธ ๋งŒ๋“ค๊ธฐ (7) ๐Ÿ…

์ง„๋ฐฉ์ด 2025. 2. 3. 20:57

  ๋งˆ์ง€๋ง‰์œผ๋กœ Study ํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค.

Study ํŽ˜์ด์ง€๋Š” Study ์ปดํฌ๋„ŒํŠธ์™€ ๋ฐ”๋Š˜์˜ ํšŒ์ „์„ ๋‹ด๋‹นํ•˜๋Š” ChimStudy ์ปดํฌ๋„ŒํŠธ๋กœ ๊ตฌํ˜„ํ•˜์˜€๋‹ค.


ChimStudy ์ปดํฌ๋„ŒํŠธ

// ChimStudy.js

import { useEffect, useState } from "react";
import Chim from "../chim/Chim";
import "../BackGround/Background.css";

export default function ChimStudy({ isStart, setIsStart, degree }) {
    const savedDegree = parseInt(localStorage.getItem("degree") || degree);
    const [currentDegree, setCurrentDegree] = useState(savedDegree);

    useEffect(() => {
        setCurrentDegree(degree);
    }, [degree]);

    useEffect(() => {
        if (!isStart) { 
            return;
        }
        
        let interval = setInterval(() => {
            setCurrentDegree((prev) => {
                if (prev <= 0) {
                    clearInterval(interval);
                    setIsStart(false);
                    localStorage.setItem("isStart", "false");
                    return 0;
                }
                const newDegree = prev - 1;
                localStorage.setItem("degree", newDegree.toString());
                return newDegree;
            });
        }, 1000);

        return () => {
            clearInterval(interval);
        };
    }, [isStart, degree]);
    
    return (
        <Chim degree={currentDegree}/>
    )
}
  • props๋กœ ํƒ€์ด๋จธ ์‹คํ–‰ ์—ฌ๋ถ€์ธ isStart, ํƒ€์ด๋จธ ๋๋‚ฌ์„ ๋•Œ false๋กœ ๋ฒˆ๊ฒฝํ•˜๊ธฐ ์œ„ํ•œ setIsStart ํ•จ์ˆ˜, ์ดˆ๊ธฐ ํšŒ์ „ ๊ฐ๋„์ธ degree ์„ธ ๊ฐ€์ง€ ๊ฐ’์„ ๋ฐ›๋Š”๋‹ค. 
  • localStorage.getItem์„ ํ†ตํ•ด ์ €์žฅ๋œ degree ๊ฐ’์„ ๋ฐ›์•„์™€ ์ •์ˆ˜๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ savedDegree์— ์ €์žฅํ•œ๋‹ค. ๊ฐ’์„ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ ๋ถ€๋ชจ์—๊ฒŒ์„œ ์ „๋‹ฌ๋œ degree ๊ฐ’์„ ์‚ฌ์šฉํ•œ๋‹ค. 
  • currentDegree์— ํ˜„์žฌ ๋ฐ”๋Š˜์˜ ํšŒ์ „ ๊ฐ๋„๋ฅผ ์ €์žฅํ•œ๋‹ค.  useState๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ์— ํŽ˜์ด์ง€๊ฐ€ ์ƒˆ๋กœ๊ณ ์นจ๋˜์–ด๋„ ๊ฐ’์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค. 
  • useEffect ๋‚ด์—์„œ isStart๊ฐ€ ๊ฑฐ์ง“์ด๋ฉด setInterval์ด ์‹คํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค. 
  • cureentDegree ๊ฐ’ <= 0 ์ผ ๊ฒฝ์šฐ clearInterval(interval); setIsStart(false);์„ ํ†ตํ•ด ํƒ€์ด๋จธ๊ฐ€ ๋ฉˆ์ถ˜๋‹ค. 
  • newDegree๋Š” ๊ฐ์†Œ๋œ currentDegree ๊ฐ’์„ ์ €์žฅํ•˜๋Š” ๋ณ€์ˆ˜์ด๋ฉฐ ์ด๋ฅผ ํ†ตํ•ด ๋ฐ”๋Š˜์ด ๋ฐ˜์‹œ๊ณ„ ๋ฐฉํ–ฅ์œผ๋กœ ํšŒ์ „ํ•œ๋‹ค. localStorage.setItem(ํ‚ค, ๊ฐ’)์„ ํ†ตํ•ด localStorage์—๋„ "degree": "๊ฐ’"์˜ ํ˜•ํƒœ๋กœ ์ €์žฅํ•œ๋‹ค. 
  • ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์–ธ๋งˆ์šดํŠธ๋  ๋•Œ return () => {clearInterval(interval);}์ด ์‹คํ–‰๋˜์–ด setInterval์„ ์ •๋ฆฌํ•œ๋‹ค. 
  • currentDegree ๊ฐ’์„ Chim ์ปดํฌ๋„ŒํŠธ์— ์ „๋‹ฌํ•˜์—ฌ currentDegree ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค ๋ฐ”๋Š˜์ด ํšŒ์ „ํ•˜๊ฒŒ ๋œ๋‹ค. 

Study ์ปดํฌ๋„ŒํŠธ

// Study.js

import { useState, useEffect } from "react";
import Background from "../BackGround/Background";
import TomatoBtn from "../TomatoBtn/TomatoBtn";
import ChimStudy from "./ChimStudy";
import pic4 from "../Pic/TomatoClock.png";
import "./Study.css";

export default function Study() {
    const savedIsStart = localStorage.getItem("isStart") === "false";
    const savedDegree = localStorage.getItem("degree") || "0";

    const [isStart, setIsStart] = useState(savedIsStart);
    const [currentDegree, setCurrentDegree] = useState(savedDegree);

    const studyM = parseInt(localStorage.getItem("studyM") || "0");
    const breakM = parseInt(localStorage.getItem("breakM") || "0");

    const handleStart = () => {
        setIsStart(true);
        setCurrentDegree(studyM * 6);
        localStorage.setItem("isStart", "true");
        localStorage.setItem("degree", studyM * 6);
    };

    const handleBreak = () => {
        setIsStart(true);
        setCurrentDegree(breakM * 6);
        localStorage.setItem("isStart", "true");
        localStorage.setItem("degree", breakM * 6);
    };

    useEffect(() => {
        return () => {
            localStorage.setItem("isStart", isStart.toString());
            localStorage.setItem("degree", currentDegree.toString());
        };
    }, [isStart, currentDegree]);

    return (
        <>
        <Background title='STUDY' />
        <div className="main">
            <div className="btn">
                <TomatoBtn name='START' className="to" onClick={handleStart} />
                <TomatoBtn name='BREAK' className="to" onClick={handleBreak} />
            </div>
            <div className="CheckTomato">
            <img src={pic4} alt='pic4' className="pic4" />
            <ChimStudy isStart={isStart} setIsStart={setIsStart} degree={currentDegree} />
            </div>
            
        </div>
        </>
    )
}
  • localStorage์—์„œ isStart ๊ฐ’์„ ๊ฐ€์ ธ์™€ false๋ฉด true๋กœ true๋ฉด false๋กœ ์„ค์ •ํ•˜์—ฌ savedIsStart์— ์ €์žฅํ•œ๋‹ค. 
  • handleStart์™€ handleBreak๋ฅผ ํ†ตํ•ด setIsStart ์ƒํƒœ๋ฅผ true๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  currentDegree์— ๊ณต๋ถ€(ํœด์‹) ์‹œ๊ฐ„์„ degree๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์ €์žฅํ•œ๋‹ค. 
  • isStart ๋˜๋Š” currentDegree ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ localStorae์— isStart, degree๋ฅผ ์ €์žฅํ•œ๋‹ค.
// Study.css

.main {
    display: flex;
    margin: 0 200px 0 200px;
}
.btn {
    margin: 80px 80px 0 0;
}
.pic4 {
    width: 687.8px;
    height: 519px;
}
.CheckTomato {
    position: relative;
}


  ์ด๋ ‡๊ฒŒ ๋„ค ํŽ˜์ด์ง€๋กœ ์ด๋ฃจ์–ด์ง„ ๋ฝ€๋ชจ๋„๋กœ ํƒ€์ด๋จธ๋ฅผ ์™„์„ฑํ•˜์˜€๋‹ค. 

์ฝ”๋“œ๊ฐ€ ์ž˜ ๋Œ์•„๊ฐ€๋Š”์ง€ ํ™•์ธํ•ด์ฃผ์–ด์•ผ ํ–ˆ๊ธฐ์— console.log๋ฅผ ์ƒ๊ฐ๋ณด๋‹ค ์ž์ฃผ, ๊ผผ๊ผผํžˆ ์‚ฌ์šฉํ•ด์•ผ ํ–ˆ๋‹ค. 

๋˜ํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์ „์— ๋Œ€๊ฐ• ์–ด๋– ํ•œ ํ๋ฆ„์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ๊ฒƒ์ธ์ง€ ์ƒ๊ฐํ•ด๋ณด์•„์•ผ ํ•จ์„ ์•Œ์•˜๋‹ค.

์ด ์ ์ด ๋ฏธํกํ–ˆ๊ธฐ์— ์ง€ํ”ผํ‹ฐ์˜ ํž˜์„ ๋งŽ์ด ๋นŒ๋ ธ๋˜ ๊ฒƒ ๊ฐ™๋‹ค. 

์ปดํฌ๋„ŒํŠธ๋กœ ๋‚˜๋ˆ„์–ด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  props๋ฅผ ํ†ตํ•ด ๊ฐ’์„ ์ฃผ๊ณ ๋ฐ›๋Š” ๊ฒƒ๋„ ๊ฝค ์–ด๋ ต๊ฒŒ ๋А๊ปด์กŒ๋‹ค.

์ด๋Ÿฌํ•œ ๋ถ€๋ถ„์€ ๋‹ค๋ฅธ ์—ฌ๋Ÿฌ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด ๋ณด๋ฉฐ ์ตํž ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋ผ ๋ฏฟ๋Š”๋‹ค.

๋‹ค์Œ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•  ๋–„๋Š” ์ด๋Ÿฌํ•œ ์ ๋“ค์„ ๊ธฐ์–ตํ•˜๋ฉฐ ๋” ํšจ์œจ์ ์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์•ผ๊ฒ ๋‹ค.

 

๋!