1. Header 구현
Header.js
import React from "react";
import "../Layout_css/Header.css";
function Header() {
return (
<header className="menu-bar">
<div className="menu-contents">
<div className="menu-title">
<a href="#Home" style={{ fontWeight: "bold" }}>
About JAEJAE
</a>
</div>
<div className="menu-list">
<div className="menu-item">
<a href="#Archiving">Archiving</a>
</div>
<div className="menu-item">
<a href="#Skills">Tech Skills</a>
</div>
<div className="menu-item">
<a href="#Project">Project</a>
</div>
<div className="menu-item">
<a href="#Contact">Contact</a>
</div>
</div>
</div>
</header>
);
}
export default Header;
- <a href="#Home"></a> 을 이용해 id="Home"인 div나 name="Home"인 a 태그로 이동이 가능하도록 함
Header.css
.menu-bar {
position: fixed;
top: 0;
right: 0;
left: 0;
background-color: beige;
z-index: 1000;
padding: 0.5rem 1rem;
box-sizing: border-box;
}
.menu-contents {
width: 100%;
display: flex;
padding: 0.6rem 1rem;
box-sizing: border-box;
justify-content: space-around;
}
.menu-list {
display: flex;
flex-direction: row;
justify-content: space-around;
}
.menu-title > a {
color: black;
font-size: clamp(1rem, 2.5vw, 1.75rem);
cursor: pointer;
text-decoration: none;
}
.menu-item {
margin: 0 1rem; /* 반응형 마진 */
}
.menu-item > a {
color: black;
font-size: clamp(0.75rem, 2vw, 1.25rem); /* 최소 1rem, 최대 1.5rem */
cursor: pointer;
text-decoration: none;
}
2. useref를 이용한 컴포넌트 간 스크롤 이동
- useRef 훅을 이용한 내부 링크 이동 구현
- 스크롤 애니메이션을 주면서 간단하게 함수로 내부링크 이동을 구현 가능
- 근데 난 App.js에 ref 객체와 스크롤 이동 함수를 구현해 놓고각 컴포넌트에 props로 넘겨주고, 각 컴포넌트에서 forwardRef를 이용해 ref를 전달받는 식으로 구현함
App.js
import React, { useRef, useState, useEffect } from "react";
import "./App.css";
import Header from "./components/Layout/Header";
import AboutDetail from "./Details/AboutDetail";
...
function App() {
const HomeRef = useRef(null);
...
const moveToHomeHandler = () => {
HomeRef.current.scrollIntoView({ behavior: "smooth" });
};
...
return (
<div className="App">
<Header
moveToHome={moveToHomeHandler}
...
/>
<AboutDetail ref={HomeRef} moveToArc={moveToHomeHandler} />
<div
ref={ArchivingRef}
...
>
<ArchivingDetail />
</div>
...
</div>
);
}
export default App;
AboutDetail.js
import React, { forwardRef } from "react";
import "../Details_css/AboutDetail.css";
const aboutDetail = forwardRef((props, ref) => {
return (
<div className="home" ref={ref}>
<div className="home-myPhoto">
...
</div>
<div className="home-about">
...
</div>
</div>
);
});
export default aboutDetail;
- 컴포넌트 전체를 forwardRef();로 감싸주면 됨
- 나머지 컴포넌트도 동일!
3. 최상단 이동버튼
1) react-icons 적용
https://react-icons.github.io/react-icons/
2) 개별 컴포넌트 구현
TopButton.js
import { useEffect, useState } from "react";
import { SlArrowUp } from "react-icons/sl";
import "./TopButton.css";
const TopButton = () => {
const [isVisible, setIsVisible] = useState(false);
const moveToTop = () => {
window.scrollTo({ top: 0, behavior: "smooth" });
};
const handleScroll = () => {
const scrollTop = window.pageYOffset;
if (scrollTop >= 40) {
setIsVisible(true);
} else {
setIsVisible(false);
}
};
useEffect(() => {
// 스크롤 이벤트 리스너를 추가
window.addEventListener("scroll", handleScroll);
// 컴포넌트가 언마운트되거나 업데이트되기 직전에 호출되는 함수를 반환
// 이 함수에서는 스크롤 이벤트 리스너를 제거
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);
return (
<div className="top-btn" onClick={moveToTop} isVisible={isVisible}>
<SlArrowUp />
</div>
);
};
export default TopButton;
4. 결과 🎉