본문 바로가기
포트폴리오

[count]자바스크립트 (js) 코드 리액트 (react) 로 마이그레이션하기 (3)

by 플라퉁 2023. 8. 26.
728x90
반응형

안녕하세요. 바로 이어서 세번째 기능인 count를 마이그레이션 해보도록 하겠습니다.

 

1편 링크 첨부합니다.

https://rhgustmfrh.tistory.com/92

 

자바스크립트 (js) 코드 리액트 (react) 로 마이그레이션하기 (1)

안녕하세요. 오늘은 기존에 만들어 놨던 포토폴리오를 리액트로 마이그레이션 하는 작업중 첫번째 글입니다. 제가 이 작업을 하는 이유에 대해 먼저 말씀 드리겠습니다. 저는 비전공자로 개발

rhgustmfrh.tistory.com

 

 

import React, { useEffect, useState } from "react";
import { useRecoilState, useRecoilValue } from "recoil";
import { counterValueState, countSelector } from "../recoil/atoms/counter";
import { useScrollPosition } from "../hooks/useScrollPosition";

const CounterComponent: React.FC = () => {
  const [counterValue, setCounterValue] = useRecoilState(counterValueState);
  const maxCount = useRecoilValue(countSelector);
  const scrollPosition = useScrollPosition();
  const [count, setCount] = useState(0);
  const donaitionRef = React.useRef<HTMLDivElement | null>(null);
  const [isAnimating, setIsAnimating] = useState(false);

  useEffect(() => {
    const startAnimation = () => {
      const el = donaitionRef.current;
      if (!el) return;
      const cont5Start = el.offsetTop - 90;
      if (scrollPosition >= cont5Start && !isAnimating) {
        setIsAnimating(true);

        let num = 0;
        const interval = setInterval(() => {
          num += counterValue.plus;
          if (num >= counterValue.complete) {
            clearInterval(interval);
            setCount(counterValue.complete);
          } else {
            setCount(num);
          }
        }, maxCount / counterValue.complete);
      }
    };
    startAnimation();
  }, [scrollPosition, count, counterValue, maxCount, isAnimating]);

  return (
    <div className="donaition">
      <div style={{ minHeight: "120vh" }}></div>
      <div className="left_count">
        <h2 data-aos="fade-up" data-aos-duration="1000">
          AI 갤러리 전시회에서 다양한<br></br>굿즈를 통한 기부를 즐기세요!
        </h2>
        <p data-aos="fade-up" data-aos-duration="1000">
          다양한 경로로 사회적 약자들에게 기부 할 수 있습니다.<br></br>전시회에
          참여하여 AI 갤러리와 기부를 함께 하세요.
        </p>
        <div className="box box1" ref={donaitionRef}>
          <p className="achieve">현재까지 모인 금액</p>
          <span className="count">{count}</span>
          <span className="price">$</span>
          <p className="dona_time">2022.11.10일 기준</p>
        </div>
        <a className="moreBtn" href="/donaition">
          자세히 보기
        </a>
      </div>
      <div className="right_ani">
        <div className="circle_wrap">
          <div className="big_bg"></div>
          <div className="small_bg"></div>
          <div className="circle_line"></div>
          <div className="circle_small">
            <div className="circle_move"></div>
          </div>
        </div>
      </div>
      <div style={{ minHeight: "120vh" }}></div>
    </div>
  );
};

export default CounterComponent;

 

페이지를 스크롤 다운하다보면 어떤 숫자가 증가하는 기능을 마이그레이션 한것입니다.

 

import { atom, selector } from "recoil";

interface CounterValue {
  plus: number;
  complete: number;
}

export const counterValueState = atom<CounterValue>({
  key: "counterValue",
  default: {
    plus: 2,
    complete: 1391
  }
});

export const countSelector = selector<number>({
  key: "countSelector",
  get: ({ get }) => {
    const counterValue = get(counterValueState);
    const speed = 10;
    const maxCount =
      Math.floor(counterValue.complete / counterValue.plus) * speed;

    return maxCount;
  }
});

해당 기능을 위한 리코일 atom 과 selector입니다.

countSelector Recoil selector, 상태에 기반하여 파생된 값을 계산합니다.

카운터 값을 관리하고 셀렉터로 최대카운트값을 selector로 계산하는 것입니다.

 

import { useState, useEffect } from "react";

export const useScrollPosition = () => {
  const [scrollPosition, setScrollPosition] = useState(0);

  const handleScroll = () => {
    const position = window.pageYOffset;
    setScrollPosition(position);
  };

  useEffect(() => {
    window.addEventListener("scroll", handleScroll);

    return () => {
      window.removeEventListener("scroll", handleScroll);
    };
  }, []);

  return scrollPosition;
};

또한 useScrollPosition 이라는 커스텀 훅도 제작하여 사용합니다.

 

스크롤을 감지하여 해당 위치값에서 카운터가 동작하기 위함입니다.

 

위와 같은 기능이 만들어집니다.

 

감사합니다.

728x90
반응형

댓글