Next.js
μtailwindcss
λ₯Ό μ΄μ©ν νλ‘μ νΈμ λλ€.
λ€λΉκ²μ΄μ λ°λ μ΅νλ¨μ λΆμ¬λλλ‘ λ§λ€μμ΅λλ€.
μ€ν¬λ‘€μ λ΄λ¦¬λ κ²½μ°μλ νμ¬ νμ΄μ§μ λ΄μ©μ μ½μ΄λ³΄λ κ²½μ°μΌ κ²μ΄κΈ° λλ¬Έμ μμμ λνκΈ° μν΄μ λ€μ΄κ²μ΄μ λ°λ₯Ό μ¨κΈ°κ³ , μ€ν¬λ‘€μ μ¬λ¦¬λ κ²½μ°λ λ€λ₯Έ νμ΄μ§λ‘ λμ΄κ°κΈ° μν¨μΌ κ²½μ°κ° λ§κΈ° λλ¬Έμ λ€λΉκ²μ΄μ λ°λ₯Ό λνλ΄λλ‘ μ€κ³νμ΅λλ€.
λ°λΌμ νμ μ΅νλ¨μ λΆμ΄ μλ€κ°
1. μ€ν¬λ‘€μ μλλ‘ λ΄λ¦¬λ κ²½μ° μ¨κΈ°κ³
2. μλ‘ μ¬λ¦¬λ κ²½μ° λνλκ³
3. μ€ν¬λ‘€μ μλλ‘ λ΄λ¦¬λλΌλ νμ΄μ§μ μ΅νλ¨μ΄λΌλ©΄ λνλλλ‘ μ€κ³νμ΅λλ€.
ν¬κ² 5κ°μ§ νμ΄μ§λ‘ ꡬλΆνμ΅λλ€.
1. μΉ΄ν
κ³ λ¦¬
2. κ²μ
3. ν
4. λ΄ μ 보
5. μ₯λ°κ΅¬λ
next.js
μ useRouter().asPath
λ₯Ό μ΄μ©ν΄μ νμ¬ URL
μ λ§λ νμ΄μ§μ λ€μ΄μ¬ κ²½μ° κ΅¬λΆν μ μλλ‘ λ€μ΄κ²μ΄μ
λ°μ νΉμ μμμ μ
νμ΅λλ€.
μ€μνκ³ μ΄λ €μ΄ μ½λκ° μλλ―λ‘ μμΈν μ½λλ μλ΅νκ² μ΅λλ€.
position: fixed
λ₯Ό μ΄μ©ν΄μ νλ¨μ κ³ μ μμΌ°μ΅λλ€.
λ€λ§ fixed
λ 곡μ€μ λ μλ λλμΌλ‘ λ€λ₯Έ μμμ λ μ΄μμμ μν₯μ λ―ΈμΉμ§ μμΌλ―λ‘ μ€μ 컨ν
μΈ κ° λ€λΉκ²μ΄μ
λ°μ 묻ν μ μκΈ° λλ¬Έμ λ€λΉκ²μ΄μ
λ°μ λμ΄λ§νΌ body
μ margin-bottom
μ λΆμ¬ν΄μ λ€λΉκ²μ΄μ
λ°κ° λ€μ΄κ° 곡κ°μ λ§λ€μμ΅λλ€.
μ€μνκ³ μ΄λ €μ΄ μ½λκ° μλλ―λ‘ μμΈν μ½λλ μλ΅νκ² μ΅λλ€.
μ²μ λ§νλ λ€λΉκ²μ΄μ λ°λ₯Ό μ€ν¬λ‘€μ μν΄μ μ¨κΈΈμ§ 보μ¬μ€μ§λ₯Ό κ²°μ νλ λ° μ¬μ©ν μ μλ ν μ λ§λ€μμ΅λλ€.
μμΈν μ€λͺ
μ μ£ΌμμΌλ‘ μμ±νκΈ° λλ¬Έμ μλ΅νκ² μ΅λλ€.
λ€λ§ μ€ν¬λ‘€ μ΄λ²€νΈ λ±λ‘νκΈ° λλ¬Έμ μ°λ‘νλ§μ μ μ©νμ΅λλ€.
src/hooks/useScroll.tsx
import { useCallback, useEffect, useState } from "react";
// util
import { throttleHelper } from "@src/libs";
/**
* λ§μ§λ§ μ€ν¬λ‘€λ§μ λ°©ν₯μ μμλ΄λ ν
* @returns [μ€ν¬λ‘€ λ°©ν₯, μ€ν¬λ‘€ μ΅νλ¨ μ¬λΆ, νμ¬ μ€ν¬λ‘€ μμΉ] μμλ‘ λ°ν ( boolean, boolean, number )
*/
const useScrollDirection = () => {
// 2022/08/09 - λ§μ§λ§ μ€ν¬λ‘€ λ°©ν₯ - by 1-blue
const [isUp, setIsUp] = useState(false);
// 2022/08/09 - νμ¬ μ€ν¬λ‘€ μμΉκ° μ μ₯ν λ³μ - by 1-blue
const [pageY, setPageY] = useState(0);
// 2022/08/09 - νμ¬ μ€ν¬λ‘€μ΄ μ΅νλ¨μ μλμ§ νλ¨ν λ³μ - by 1-blue
const [isBottom, setIsBottom] = useState(false);
// 2022/08/09 - νμ¬ μ€ν¬λ‘€ λ°©ν₯μ νμΈν μ€ν¬λ‘€ μ΄λ²€νΈ ν¨μ - by 1-blue
const handleScroll = useCallback(() => {
/**
* scrollHeight: μ΄ μ»¨ν
μΈ λμ΄
* clientHeight: νμ¬ λ³΄μ΄λ λμ΄ ( νμ¬ νλ©΄(컨ν
μΈ )μ λμ΄ )
* scrollY: νμ¬ μ€ν¬λ‘€ λμ΄
*
* λ°λΌμ "μ΄ μ»¨ν
μΈ λμ΄ === νμ¬ λ³΄μ΄λ λμ΄ + νμ¬ μ€ν¬λ‘€ λμ΄" λΌλ©΄ μ΅νλ¨κΉμ§ μ€ν¬λ‘€μ λ΄λ¦° κ²
*/
const {
scrollY,
document: {
documentElement: { scrollHeight, clientHeight },
},
} = window;
const deltaY = scrollY - pageY;
const isUp = scrollY !== 0 && deltaY >= 0;
const isBottom = scrollHeight - scrollY - clientHeight === 0;
setIsUp(isUp);
setPageY(scrollY);
setIsBottom(isBottom);
}, [pageY, setIsUp, setPageY, setIsBottom]);
// 2022/08/09 - μ€ν¬λ‘€ μ΄λ²€νΈμ μ€λ‘νλ§ μ μ© - by 1-blue
const throttleScroll = throttleHelper(handleScroll, 50);
// 2022/08/09 - μ€ν¬λ‘€ μ΄λ²€νΈ λ±λ‘ - by 1-blue
useEffect(() => {
document.addEventListener("scroll", throttleScroll);
return () => document.removeEventListener("scroll", throttleScroll);
}, [throttleScroll]);
return [isUp, isBottom, pageY];
};
export default useScrollDirection;
src/libs/utils.ts
/**
* μ€λ‘νλ§ μ μ© ν¬νΌ ν¨μ
* @param callback μ΄νμ μ€νν μ½λ°±ν¨μ
* @param waitTime κΈ°λ€λ¦΄ μκ°
* @returns "waitTime"λ§νΌ μ€λ‘νλ§μ΄ μ μ©λ ν¨μ("callback") λ°ν
*/
export const throttleHelper = (callback: () => void, waitTime: number) => {
let timerId: ReturnType<typeof setTimeout> | null = null;
return () => {
if (timerId) return;
timerId = setTimeout(() => {
callback();
timerId = null;
}, waitTime);
};
};