본문 바로가기

Project/portfolio

포트폴리오 header 완성하기 | clsx, useActiveSectionContext

반응형

 

 

 

 

토글

 

 

export default function Header() {
  const { activeSection, setActiveSection, setTimeOfLastClick } =
    useActiveSectionContext();

 

useActiveSectionContext 훅을 사용해서 변수들을 가져온다.

 

 

 

          {links.map((link) => (
            <motion.li
              className="h-3/4 flex items-center justify-center relative"
              key={link.hash}
              initial={{ y: -100, opacity: 0 }}
              animate={{ y: 0, opacity: 1 }}
            >

 

map함수로 links 배열을 순회하면서 네비게이션바 페이지 링크를 생성한다. 

 

 

              <Link
                className={clsx(
                  "flex w-full items-center justify-center px-3 py-3 hover:text-gray-950 transition dark:text-gray-500 dark:hover:text-gray-300",
                  {
                    "text-gray-950 dark:text-gray-200":
                      activeSection === link.name,
                  }
                )}
                href={link.hash}
                onClick={() => {
                  setActiveSection(link.name);
                  setTimeOfLastClick(Date.now());
                }}
              >
                {link.name}

                {link.name === activeSection && (
                  <motion.span
                    className="bg-gray-100 rounded-full absolute inset-0 -z-10 dark:bg-gray-800"
                    layoutId="activeSection"
                    transition={{
                      type: "spring",
                      stiffness: 380,
                      damping: 30,
                    }}
                  ></motion.span>
                )}
              </Link>
            </motion.li>
          ))}
        </ul>
      </nav>
    </header>
  );
}

 

Link 컴포넌트로 감싸져있으며

클릭시 해당 섹션으로 스크롤된다.

 

그리고 링크가 활성화된 상태일때는 다른 스타일이 적용되도록 한다.

 

반응형

 

 

useActiveSectionContext

export const ActiveSectionContext =
  createContext<ActiveSectionContextType | null>(null);

 

ActiveSectionContext라는 이름의 컨텍스트를 생성. 타입 값 또는 null 값을 가질 수 있다.

 

 

export default function ActiveSectionContextProvider({
  children,
}: ActiveSectionContextProviderProps) {
  const [activeSection, setActiveSection] = useState<SectionName>("Home");
  const [timeOfLastClick, setTimeOfLastClick] = useState(0);

 

ActiveSectionContextProvider 컴포넌트를 정의한다.

useState를 사용하여 activeSection과 timeOfLastClick라는 두 개의 상태를 관리한다.

 

 

 

  return (
    <ActiveSectionContext.Provider
      value={{
        activeSection,
        setActiveSection,
        timeOfLastClick,
        setTimeOfLastClick,
      }}
    >
      {children}
    </ActiveSectionContext.Provider>
  );
}

 

ActiveSectionContextProvider 컴포넌트가 자식 컴포넌트들에게 ActiveSectionContext를 제공.

 

 

export function useActiveSectionContext() {
  const context = useContext(ActiveSectionContext);

  if (context === null) {
    throw new Error(
      "useActiveSectionContext must be used within an ActiveSectionContextProvider"
    );
  }

  return context;
}

 

 useActiveSectionContext 커스텀 훅을 정의.

ActiveSectionContext의 값을 가져온다.

만약 이 훅이 ActiveSectionContextProvider 내부에서 사용되지 않는다면, 오류를 발생시킨다.

 

 

 

 

 

 

 

반응형