Skip to content

Commit

Permalink
refactor: 네비게이션(SiteNav) 컴포넌트 클래스 -> 함수 컴포넌트로 수정
Browse files Browse the repository at this point in the history
  • Loading branch information
pozafly committed Nov 15, 2023
1 parent 0f5b010 commit 23311e3
Showing 1 changed file with 106 additions and 127 deletions.
233 changes: 106 additions & 127 deletions src/components/header/SiteNav.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createRef, Fragment, PureComponent } from 'react';
import { Fragment, useCallback, useEffect, useRef, useState } from 'react';

import { css } from '@emotion/react';
import styled from '@emotion/styled';
Expand Down Expand Up @@ -28,145 +28,126 @@ type SiteNavProps = {
};
};

type SiteNavState = {
showTitle: boolean;
};

class SiteNav extends PureComponent<SiteNavProps, SiteNavState> {
titleRef = createRef<HTMLSpanElement>();
lastScrollY = 0;
ticking = false;
state = { showTitle: false };

componentDidMount(): void {
this.lastScrollY = window.scrollY;
if (this.props.isPost) {
window.addEventListener('scroll', this.onScroll, { passive: true });
}
}
export default function SiteNav({ isHome = false, isPost, post }: SiteNavProps) {
const [showTitle, setShowTitle] = useState(false);
const titleRef = useRef<HTMLSpanElement>(null);
const lastScrollY = useRef<number>(0);
const ticking = useRef<boolean>(false);

componentWillUnmount(): void {
window.removeEventListener('scroll', this.onScroll);
}

onScroll = () => {
if (!this.titleRef || !this.titleRef.current) {
const onScroll = useCallback(() => {
if (!titleRef || !titleRef.current) {
return;
}

if (!this.ticking) {
requestAnimationFrame(this.update);
if (!ticking.current) {
requestAnimationFrame(update);
}
ticking.current = true;
}, []);

this.ticking = true;
};

update = () => {
if (!this.titleRef || !this.titleRef.current) {
const update = () => {
if (!titleRef || !titleRef.current) {
return;
}

this.lastScrollY = window.scrollY;

const trigger = this.titleRef.current.getBoundingClientRect().top;
const triggerOffset = this.titleRef.current.offsetHeight + 35;
lastScrollY.current = window.scrollY;
const trigger = titleRef.current.getBoundingClientRect().top;
const triggerOffset = titleRef.current.offsetHeight + 35;

// show/hide post title
if (this.lastScrollY >= trigger + triggerOffset) {
this.setState({ showTitle: true });
if (lastScrollY.current >= trigger + triggerOffset) {
setShowTitle(true);
} else {
this.setState({ showTitle: false });
setShowTitle(false);
}

this.ticking = false;
ticking.current = false;
};

render() {
const { isHome = false, isPost = false, post } = this.props;
return (
<Fragment>
<nav css={SiteNavStyles}>
<SiteNavLeft className={`site-nav-left ${isHome ? 'is-home' : ''}`}>
<SiteNavLogo />
<SiteNavContent css={[this.state.showTitle ? HideNav : '']}>
<ul css={NavStyles} role="menu">
<li role="menuitem">
<Link
to="/"
activeClassName="nav-current"
className={`${isHome ? 'is-home' : ''}`}
>
Home
</Link>
</li>
<li role="menuitem">
<Link
to="/about"
activeClassName="nav-current"
className={`${isHome ? 'is-home' : ''}`}
>
About
</Link>
</li>
<li role="menuitem">
<Link
to="/tags"
activeClassName="nav-current"
className={`${isHome ? 'is-home' : ''}`}
>
Tags
</Link>
</li>
<li role="menuitem">
<Link
to="/tags/diary/"
activeClassName="nav-current"
className={`${isHome ? 'is-home' : ''}`}
>
Diary
</Link>
</li>
</ul>
{isPost && (
<NavPostTitle ref={this.titleRef} className="nav-post-title">
{post?.title || ''}
</NavPostTitle>
)}
</SiteNavContent>
</SiteNavLeft>
<SiteNavRight>
<SocialLinks>
{config.instagram && (
<a
className={`${isHome ? 'is-home' : ''} not-mobile`}
css={[SocialLink, SocialLinkFb]}
href={config.instagram}
target="_blank"
title="Instagram"
rel="noopener noreferrer"
useEffect(() => {
lastScrollY.current = window.scrollY;
if (isPost) {
window.addEventListener('scroll', onScroll, { passive: true });
}
return () => window.removeEventListener('scroll', onScroll);
}, [isPost, onScroll]);

return (
<Fragment>
<nav css={SiteNavStyles}>
<SiteNavLeft className={`site-nav-left ${isHome ? 'is-home' : ''}`}>
<SiteNavLogo />
<SiteNavContent css={[showTitle ? HideNav : '']}>
<ul css={NavStyles} role="menu">
<li role="menuitem">
<Link to="/" activeClassName="nav-current" className={`${isHome ? 'is-home' : ''}`}>
Home
</Link>
</li>
<li role="menuitem">
<Link
to="/about"
activeClassName="nav-current"
className={`${isHome ? 'is-home' : ''}`}
>
<Instagram />
</a>
)}
{config.github && (
<a
className={`${isHome ? 'is-home' : ''} not-mobile`}
css={SocialLink}
href={config.github}
title="Github"
target="_blank"
rel="noopener noreferrer"
About
</Link>
</li>
<li role="menuitem">
<Link
to="/tags"
activeClassName="nav-current"
className={`${isHome ? 'is-home' : ''}`}
>
<Github />
</a>
)}
<ThemeModeSwitch isHome={isHome} />
</SocialLinks>
</SiteNavRight>
</nav>
</Fragment>
);
}
Tags
</Link>
</li>
<li role="menuitem">
<Link
to="/tags/diary/"
activeClassName="nav-current"
className={`${isHome ? 'is-home' : ''}`}
>
Diary
</Link>
</li>
</ul>
{isPost && (
<NavPostTitle ref={titleRef} className="nav-post-title">
{post?.title || ''}
</NavPostTitle>
)}
</SiteNavContent>
</SiteNavLeft>
<SiteNavRight>
<SocialLinks>
{config.instagram && (
<a
className={`${isHome ? 'is-home' : ''} not-mobile`}
css={[SocialLink, SocialLinkFb]}
href={config.instagram}
target="_blank"
title="Instagram"
rel="noopener noreferrer"
>
<Instagram />
</a>
)}
{config.github && (
<a
className={`${isHome ? 'is-home' : ''} not-mobile`}
css={SocialLink}
href={config.github}
title="Github"
target="_blank"
rel="noopener noreferrer"
>
<Github />
</a>
)}
<ThemeModeSwitch isHome={isHome} />
</SocialLinks>
</SiteNavRight>
</nav>
</Fragment>
);
}

const SiteNavStyles = css`
Expand Down Expand Up @@ -312,5 +293,3 @@ const HideNav = css`
opacity: 1;
}
`;

export default SiteNav;

0 comments on commit 23311e3

Please sign in to comment.