React를 기반으로 자기소개 사이트를 SPA로 구현하는 토이 프로젝트입니다.
본 사이트는 헤더와 메인 배너를 기본으로 하며 Nav에 따라 커리어, 스킬, 포트폴리오 등을 나타내는 섹션으로 구성되어 있습니다.
🏠 배포 링크 보러가기
✏ Velog 포스팅: JS프로젝트를 TS로 리팩토링하기
- outlet을 이용한 부분적 리렌더링
- 반응형으로 특정 px이하로 화면이 작아지면 다른 UI 표시
const Layout = () => {
return (
<>
<Header />
<Banner />
<Nav />
<Outlet />
<Footer />
</>
);
};
function App() {
const isPCscreenOrTablet = useMediaQuery({ query: "(min-width:1024px)" });
return (
<div className="App">
{isPCscreenOrTablet ? (
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<History />} />
<Route path="skills" element={<Skills />} />
<Route path="portfolio" element={<Portfolio />} />
<Route path="practice" element={<Practice />} />
</Route>
</Routes>
) : (
<Incomplete />
)}
</div>
);
}
- state를 이용하여 스킬에 대한 설명이 아이콘 우측에 뜨도록 구현
- 스킬 아이콘 클릭 시 해당 스킬의 index값을 setter를 통해 저장하여 각각 다른 설명 내용을 보여줌
export const Skills = () => {
const skills = data.skills;
const [active, setActive] = useState(4);
const handleClick = (id: number) => {
setActive(id);
};
return (
<S.SectionContainer>
<S.ContentsWrap>
{/* ... */}
<S.IconsWrap>
{skills.main.map((data, index) => (
<S.Icon
key={index}
className={data.name}
onClick={() => handleClick(index)}
>
<img src={data.icon} alt={data.name} />
</S.Icon>
))}
</S.IconsWrap>
{/* ... */}
<S.DescWrap>
<h2>{skills.main[active].name}</h2>
<S.DescText>
{skills.main[active].desc.map((data: string) => (
<p>· {data}</p>
))}
</S.DescText>
</S.DescWrap>
</S.ContentsWrap>
</S.SectionContainer>
);
};
- 포트폴리오 클릭시 데이터 전달 후 해당 정보를 모달창으로 그려냄
export const Portfolio = () => {
const [isModalOpen, setModalOpen] = useState(false);
const [modalData, setModalData] = useState<product>(null);
const modalOpen = (data: product) => {
setModalData(data);
setModalOpen((prev) => !prev);
};
const modalClose = () => {
setModalOpen((prev) => !prev);
};
return (
<S.SectionContainer>
{/* component 내용 */}
{isModalOpen && (
<PortfolioModal data={modalData} toggleClose={modalClose} />
)}
</S.SectionContainer>
);
};
- React
- TypeScript
- react-router-dom
- styled-components
- react-responsive
- react-fontawesome