How can I make a Top Button, click to scroll to the top ?!
์๋น์ค์ฉ ํํ์ด์ง๋ฅผ ๊ฐ๋ฐํ๋ค ๋ณด๋ฉด ํญ์ ๊ตฌํํด์ผ ํ๋ ๋ถ๋ถ์ ์คํฌ๋กค ์ ๋๋ค.
์ฒ์์๋ ๋ฌด์กฐ๊ฑด ref ๋ฅผ ์ฌ์ฉํด์ ์ปจํธ๋ด ํด์ผ ํ๋ค๊ณ ์๊ฐํ์๋๋ฐ, ์ด์จ๋ ๋ฆฌ์กํธ๋ ์๋ฐ์คํฌ๋ฆฝํธ๋ค ๋ณด๋ ๊ผญ ๊ทธ๋ ์ง๋ง์ ์๋๋ผ๊ตฌ์. useEffect์์ addEventListener๋ฅผ ๊ฑธ์ด์ฃผ๊ณ removeEventListener๋ก clean-up์ ํด์ฃผ๊ธฐ๋ง ํ๋ฉด ๋๋๋ผ๊ตฌ์. ์๊ฐ๋ณด๋ค ๊ฐ๋จํ๊ฒ ๊ตฌํ ํ ์ ์์์ต๋๋ค.
๋ค์๊ณผ ๊ฐ์ด ํด๋ฆญํ๋ฉด ํ์ด์ง ์ต์๋จ์ผ๋ก ์คํฌ๋กค ๋๋ ๊ธฐ๋ฅ์ ๊ตฌํํด ๋ณด๊ณ ์ ํฉ๋๋ค.
์ฐ์ ๊ตฌ์กฐ๋ฅผ ์ก์๋ณด๊ฒ ์ต๋๋ค.
<div className="wrap">
<button className="topBtn">TOP</button>
<div className="inner">
<h1>Fixed Scroll Top</h1>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Mollitia, voluptas ratione libero earum alias, officia temporibus magni possimus atque rem distinctio autem unde eaque. Minus quaerat odio mollitia asperiores neque?
...
</div>
</div>
CSS๋ ๋ฏธ๋ฆฌ ์ฌ๋ ค๋๊ฒ ์ต๋๋ค. ๋์์ธ์ ์กฐ๊ธ์ด๋ผ๋ ์ด์๊ฒ ํ๊ณ ์ ๋ ธ์ค๋ ฅ ํ์ง๋ง.. ๐
CSS๋ ๋ฐ๋ก ์ค๋ช ๋๋ฆฌ์ง ์๊ฒ ์ต๋๋ค.
.wrap {
position: relative;
padding: 30px;
font-size: 18px;
line-height: 1.6;
background: lightgray;
}
.topBtn {
position: fixed;
opacity: 0;
bottom: 40px;
right: 40px;
z-index: -10;
width: 50px;
height: 50px;
border-radius: 100%;
border: 0 none;
background: lightpink;
color: blueviolet;
border: 2px solid blueviolet;
font-size: 18px;
font-weight: bold;
letter-spacing: -0.06em;
box-shadow: 1px 1px 6px 3px rgba(0,0,0,0.3);
cursor: pointer;
transition: opacity 0.3s ease-in;
}
.topBtn.active {
z-index: 10;
opacity: 1;
}
.topBtn:hover,
.topBtn:focus,
.topBtn:active {
outline: 0 none;
}
์, ๊ทธ๋ผ ๊ตฌํํ๊ณ ์ถ์ ๋ด์ฉ์ ์ ๋ฆฌํด๋ณด๊ฒ ์ต๋๋ค!
1. ์คํฌ๋กค์ 100px ์ด์ ๋ด๋ฆฌ๋ฉด TOP ๋ฒํผ์ด ๋ํ๋๋ค.
2. TOP๋ฒํผ์ ํด๋ฆญํ๋ฉด ์คํฌ๋กค๋ฆฌ ์ต์๋จ์ผ๋ก ์ฌ๋ผ๊ฐ๋ค.
์ฐ์ ์คํฌ๋กค์ ๊ฐ์ ์๊ธฐ ์ํด ScrollY ๋ผ๋ ์ด๋ฆ์ผ๋ก state๋ฅผ ๋ง๋ฆ๋๋ค.
๊ทธ๋ฆฌ๊ณ ํจ์๋ฅผ ํ๋ ์ ์ํ์ฌ window.pageYoffset ๊ฐ์ ScrollY ์ ์ ์ฅ ํฉ๋๋ค.
์ด ๋ถ๋ถ์ ์คํฌ๋กค ํ ๋๋ง๋ค ๋ฐ๋ณตํ๋ฉด window์ ์คํฌ๋กค ๊ฐ์ด ScrollY์ ์ ์ฅ๋๊ณ , ScrollY์ ๊ฐ์ด ์ ์ฅ๋๋ฉด์ useEffect๋ฅผ ํตํด ์ค์๊ฐ์ผ๋ก ๋ฐ๋๋ ScrollY์ ๊ฐ์ ์ ์ ์๊ฒ ์ง์?
const [ScrollY, setScrollY] = useState(0); // ์คํฌ๋กค๊ฐ์ ์ ์ฅํ๊ธฐ ์ํ ์ํ
const handleFollow = () => {
setScrollY(window.pageYOffset); // window ์คํฌ๋กค ๊ฐ์ ScrollY์ ์ ์ฅ
}
useEffect(() => {
console.log("ScrollY is ", ScrollY); // ScrollY๊ฐ ๋ณํํ ๋๋ง๋ค ๊ฐ์ ์ฝ์์ ์ถ๋ ฅ
}, [ScrollY])
useEffect(() => {
const watch = () => {
window.addEventListener('scroll', handleFollow);
}
watch(); // addEventListener ํจ์๋ฅผ ์คํ
return () => {
window.removeEventListener('scroll', handleFollow); // addEventListener ํจ์๋ฅผ ์ญ์
}
})
์ง๊ธ ๊ฐ์ด ์คํฌ๋กค์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ์ฒ๋ผ ํ ๋ฒ ์คํํ๋ ๊ฒ์ด ์๋ ์ฌ๋ฌ๋ฒ addEventListener๋ฅผ ์ฌ์ฉํ ๋์๋ removeEventListener๋ฅผ ๊ผญ ํด์ฃผ์ธ์!
๊ทธ๋ ์ง ์์ผ๋ฉด ์ฌ๋ฌ๋ฒ ํธ์ถ ๋๊ณ , ๋ฉ๋ชจ๋ฆฌ์ gabarge collect
์ด๋ ๊ฒ ์คํฌ๋กค์ ์์น๊ฐ์ ์ ์ ์์ต๋๋ค.
๊ทธ๋ฌ๋ฉด ๋๋จธ์ง๋ ๋ ์ฝ์ง์.
์ ๋ ์์๋ก ์คํฌ๋กค์ด 100์ ๋ ๋ด๋ ค๊ฐ๋ฉด ๋ฒํผ์ด ๋ํ๋๊ฒ ํ์์ต๋๋ค.
์ํ์ ๋ฐ๋ผ ๋ฒํผ์ ๋ณด์ด๊ณ ์๋ณด์ด๊ณ ๋ฅผ ๊ฒฐ์ ํ๋ BtnStatus ๊ฐ์ ํ๋ ๋์์ต๋๋ค.
๋ฌผ๋ก ์๋์ ์์์ฒ๋ผ ๋ฒํผ์ ์์ ๋ ๋๋ฅผ ํ๋๋ ์ํ๋๋๋ก ํ ์ ์์ต๋๋ค.
{ BtnStatus &&<button className="topBtn">TOP</button> }
ํ์ง๋ง ์ ๋ opcity์ transition์ ํตํด ์ข ๋ ๋ถ๋๋ฌ์ด ํจ๊ณผ๋ฅผ ์ฃผ๊ณ ์ถ์ด์ ๊ทธ๋ฅ ํด๋์ค๋ก ์ ์ดํ์์ต๋๋ค.
import { useState, useEffect } from 'react'
import './App.css';
function App() {
const [ScrollY, setScrollY] = useState(0);
const [BtnStatus, setBtnStatus] = useState(false); // ๋ฒํผ ์ํ
const handleFollow = () => {
setScrollY(window.pageYOffset);
if(ScrollY > 100) {
// 100 ์ด์์ด๋ฉด ๋ฒํผ์ด ๋ณด์ด๊ฒ
setBtnStatus(true);
} else {
// 100 ์ดํ๋ฉด ๋ฒํผ์ด ์ฌ๋ผ์ง๊ฒ
setBtnStatus(false);
}
}
const handleTop = () => { // ํด๋ฆญํ๋ฉด ์คํฌ๋กค์ด ์๋ก ์ฌ๋ผ๊ฐ๋ ํจ์
window.scrollTo({
top: 0,
behavior: "smooth"
});
setScrollY(0); // ScrollY ์ ๊ฐ์ ์ด๊ธฐํ
setBtnStatus(false); // BtnStatus์ ๊ฐ์ false๋ก ๋ฐ๊ฟ => ๋ฒํผ ์จ๊น
}
useEffect(() => {
const watch = () => {
window.addEventListener('scroll', handleFollow)
}
watch();
return () => {
window.removeEventListener('scroll', handleFollow)
}
})
return (
<div className="wrap">
<button
className={BtnStatus ? "topBtn active" : "topBtn"} // ๋ฒํผ ๋
ธ์ถ ์ฌ๋ถ
onClick={handleTop} // ๋ฒํผ ํด๋ฆญ์ ํจ์ ํธ์ถ
>TOP</button>
<div class="inner">
<h1>Fixed Scroll Top</h1>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Mollitia, voluptas ratione libero earum alias, officia temporibus magni possimus atque rem distinctio autem unde eaque. Minus quaerat odio mollitia asperiores neque?
...
</div>
</div>
);
}
export default App;
์ด๋ ๊ฒ ๊ตฌํํ์์ต๋๋ค. ์๊ฐ ๋ณด๋ค ์์ค๋ ์งง๊ณ ๊ฐํธํด์ ๋ง์์ ๋ญ๋๋ค.
๋ฌผ๋ก Scroll ๋ถ๋ถ๋ง ๋ฐ๋ก ์ปดํฌ๋ํธ๋ก ๊ด๋ฆฌ๋ฅผ ํ๋ฉด ๋์ฑ ์ข๊ฒ ๋ค์!
์ ๋ ์ํ ์์ค๋ผ ๊ทธ๋ฅ ํ ๊ณณ์ ์์ฑํ์์ต๋๋ค.
scroll ๊ด๋ จํ์ฌ ๋ง์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์๊ณ ref๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ๋ ์์ต๋๋ค.
๊ฐ ํ๋ก์ ํธ ์ํฉ์ ๋ง๊ฒ ์ฐพ์์ ์ ์ฉํ์๋ฉด ๋๊ฒ ์ต๋๋ค.
์ ๋ ์ค์ํ๊ฒ ์ปจํธ๋กค ํ๋ ๋ถ๋ถ์ด ์๋๋ผ์ ์ต๋ํ ์์ด ๋ ๊ฐ๊ณ ๊ฐ๋จํ๊ฒ ๊ตฌํํ ์ ์๋ ๊ฒ์ ์ฐพ๋ค๋ณด๋ ์ด๋ ๊ฒ ๊น๋ํ๊ฒ ๊ตฌํํ ์ ์๋ ์์ค๋ฅผ ์ฐพ์์ ๊ณต์ ๋๋ฆฝ๋๋ค.
์ค๋๋ ์ด๋ ๊ฒ ํ ํ ๋ง ๋ฐฐ์ฐ๋ค์!
ํด๋น ์์ค๊ฐ ๋์์ด ๋์ จ๋ค๋ฉด, ์ ๋ ๊ธฐ์ฉ๋๋ค! ๐ฅฐ
๊ทธ๋ผ ๋ค๋ค ์ฆ๊ฑฐ์ด ์ฝ๋ฉ ํ์ธ์!
'๊ฐ๋ฐ ๐พ > ReactJS' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[React][ํ๊ฒฝ์ธํ ] react-router-dom ์ฌ์ฉํ๊ธฐ (0) | 2021.05.25 |
---|---|
[์๋ฌ๋ ธํธ] defaultState for reducer handling [object Object] should be defined (0) | 2021.03.17 |
๋ชจ๋๊ฐ ์์ฃผ ์ฌ์ฉํ๋ React ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ ๋ฆฌ (0) | 2021.02.06 |
React-datepicker ์ปค์คํ ํ๊ธฐ (2) | 2021.02.02 |
React ์คํ์ผ๋ง - emotion (3) | 2021.02.01 |