02. 발등에 next.js + sanity 떨어짐

0x3den·2023년 6월 11일
0
post-thumbnail

next.js + sanity를 활용한 포트폴리오 사이트를 만들겠다고 얘기한 이후인 2월의 어느날, 포폴을 제출해야 했다. 2월 3째주에 몰아서 작업한 기록을 이제서야 포스팅해본다.


시리즈의 첫번째 포스팅은 1월 말이었는데...벗...그 후로 상황이 많이 달라졌다.

난 분명 야금야금 만들고 싶었는데...
1)포폴 제출 요청이 들어왔고, 2)링크로 포폴을 제출하고 싶었고, 3)제출하려면 만들어야 했다.
🤦‍♀️

제출하려면 해야지!

2월 셋째주에 몰아서 커밋한 깃헙 기록

2월 셋째주에 몰아서 작업했다.
제출하고 지쳐서 한동안 안건드리다가... 저번달부터 다시 야금야금 고쳐보고 있다.

5개월만의 포스팅이니 만큼, 이번 포스팅은
2월 셋째주에 작업한 깃헙 커밋...되새김질이 되겠다.


1. 이력 표시 : month도 표시하기

기존 schema에서 인풋값은 년-월-일-시-분 까지 다 받고 있었으나 아웃풋은 2019 - 2020 처럼 year만 표시하고 있었다. 하지만 난 2020.03 - 2020.11 이렇게 표시하고 싶었지.

그래서 다음과 같이 수정했다.

코드를 들고와서 다시 보자면
(나는 디자이너라 챗 gpt의 도움을 받았다...^^)

  • date object의 month0부터 시작하므로 +1을 더해서 표시한다.
  • duration 이 존재하지 않으면 undefined로 표시
  • duration.start 가 존재하지 않는다면 undefined로 표시
  • duration.end 가 존재하지 않는다면, endYearNow로, endMonthundefined로 표시
  • startYearendYear가 모두 존재할 때만 렌더링, startMonthendMonthundefined인 경우는 월을 표시하지 않음
const startYear = new Date(duration?.start).getFullYear()
const startMonth = duration?.start? new Date(duration.start).getMonth() + 1 : undefined
const endYear = duration?.end? new Date(duration?.end).getFullYear() : 'Now'
const endMonth = duration?.end? new Date(duration.end).getMonth() + 1 : undefined
  
  return (
    <div>
      <div className="mb-20">
...
            {!!(startYear && endYear) && (
              <div className="p-3 lg:p-4">
                <div className="text-xs md:text-sm">Duration</div>
                <div className="text-md md:text-lg">{`${startYear}.${startMonth} -  ${endYear}.${endMonth}`}</div>
              </div>
            )}

스위프트 배울 시절 옵셔널 체이닝에 정신이 아득해졌던 기억이 있는데, 타입스크립트에도... 있네....!

2. Navbar mobile 버전 추가

next.js + sanity의 다른 템플릿을 참고해서 작업했던 것 같은데 아니었다. 챗gpt랑 작업했네.
챗gpt에게 요청한 문구 캡처

the navbar that I code like this. but I want to add responsible menu for mobile, like hamburger menu. my code is like this. could you edit it? = 지금 내코드 이런데 모바일 대응하게 수정해줄래?

그래서 챗gpt랑 합의 본 코드는 다음과 같다.

  • 'use client' & useState 넣기
    : 왜 넣었는지 기억이 안나서 다시 빼봤는데 다음과 같은 에러가 떴다.
    You're importing a component that needs useState. It only works in a Client Component but none of its parents are marked with "use client", so they're Server Components by default.

    공식 설명 링크
    -> next.js는 SSR(서버 사이드 렌더링)과 CSR(클라이언트 사이드 렌더링)을 처리를 다르게 하는데, SSR되는 컴포넌트 중에 CSR로 되어야하는 부분이 생긴다면 (e.g. useState) 파일의 맨 위에 'use client'를 정의해서 클라이언트 번들의 일부로 인식되게끔 한다.

  • isMenuOpen 으로 상태 관리
    :

'use client'

import { MenuIcon, CloseIcon } from '@sanity/icons'
import { resolveHref } from 'lib/sanity.links'
import Link from 'next/link'
import { useState } from 'react'
import { MenuItem } from 'types'

interface NavbarProps {

export function Navbar({ menuItems }: NavbarProps) {
  const [isMenuOpen, setIsMenuOpen] = useState(false)

  return (
	...

      {/* Hamburger menu for mobile*/}
      <div className="flex md:hidden">
        <button
          type="button"
          className="text-gray-600 hover:text-black focus:outline-none"
          onClick={() => setIsMenuOpen(!isMenuOpen)}
        >
          {isMenuOpen ? (
            <CloseIcon className="h-6 w-6" />
          ) : (
            <MenuIcon className="h-6 w-6" />
          )}
        </button>
      </div>
      
      {/* Menu items */}
      <div
        className={`${
          isMenuOpen ? 'block' : 'hidden'
        } md:flex md:items-center w-full md:w-auto`}
      >
        {menuItems &&
          menuItems.map((menuItem, key) => {
            const href = resolveHref(menuItem?._type, menuItem?.slug)
            if (!href || menuItem?._type === 'home') {
              return null
            }
            return (
              ...
            )
          })}
      </div>
    </div>
  )
}

앞으로 얘기할 수 있는 것들

  • iframe : 비교적 최근에 오류 수정을 끝냄
    • vimeo autoplay 적용되지 않는 에러 해결
    • studio preview에서 iframe 미리보기 (하는중)
  • font : 최근에 어도비 폰트도 적용함
    • 어도비 폰트 적용
    • 로컬 폰트 적용
profile
Web3 Product Designer

0개의 댓글