728x90
반응형
안녕하세요. 바로 이어서 세번째 기능인 count를 마이그레이션 해보도록 하겠습니다.
1편 링크 첨부합니다.
https://rhgustmfrh.tistory.com/92
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
반응형
'포트폴리오' 카테고리의 다른 글
[validation]자바스크립트 (js) 코드 리액트 (react) 로 마이그레이션하기 (4) (0) | 2023.08.26 |
---|---|
[swiper, aos]자바스크립트 (js) 코드 리액트 (react) 로 마이그레이션하기 (2) (0) | 2023.08.26 |
[dropdown]자바스크립트 (js) 코드 리액트 (react) 로 마이그레이션하기 (1) (0) | 2023.08.26 |
React와 TensorFlow.js로 BTC 비트코인 예측 웹앱 만들기: 머신러닝 기반 프로젝트 튜토리얼 (0) | 2023.08.17 |
React와 TensorFlow.js로 당뇨병 예측 웹앱 만들기: 머신러닝 기반 프로젝트 튜토리얼 (0) | 2023.08.09 |
댓글