리액트 icon 컴포넌트 + NavLink 사용

Sheryl Yun·2023년 9월 18일
0

veltrends

목록 보기
1/1
post-thumbnail

Veltrends 깃허브를 보다가 금방 써 먹을 수 있겠다 싶은 코드를 발견해서 가져왔다.

Footer와 FooterItem을 구현하는 컴포넌트이다.

배운 것

  • icon과 to 링크 추상화하기
// Footer.tsx

import styled from '@emotion/styled'
import { colors } from '~/lib/colors'
import { media } from '~/lib/media'
import FooterTabItem from './FooterTabItem'

function Footer() {
  return (
    <StyledFooter>
      <FooterTabItem icon="home" to="/" />
      <FooterTabItem icon="search" to="/search" />
      <FooterTabItem icon="plus-circle" to="/write" />
      <FooterTabItem icon="bookmark" to="/bookmarks" />
      <FooterTabItem icon="setting" to="/setting" />
    </StyledFooter>
  )
}

const StyledFooter = styled.footer`
  height: 56px;
  border-top: 1px solid ${colors.gray0};
  display: flex;
  ${media.mobile} {
    display: none;
  }
`

export default Footer
  • Map 형태 사용과 keyof typeof로 타입 정의하기
  • NavLink의 active (회사에서 배운 거 복습)
// FooterItem.tsx

import { NavLink } from '@remix-run/react'
import React from 'react'
import styled from '@emotion/styled'
import { colors } from '~/lib/colors'
import { Bookmark, Home, PlusCircle, Search, Setting } from '../vectors'
import { css } from '@emotion/react'

const iconMap = {
  home: Home,
  search: Search,
  'plus-circle': PlusCircle, // key의 두 단어를 이을 때 케밥 케이스 + 홑따옴표
  bookmark: Bookmark,
  setting: Setting,
}

interface Props {
  icon: keyof typeof iconMap
  to: string
}

function FooterTabItem({ icon, to }: Props) {
  const iconEl = React.createElement(iconMap[icon]);
  
  return (
    <LinkItem
      to={to}
      className={({ isActive }) => {
        if (isActive) return 'active'
        return ''
      }}
    >
      {iconEl}
    </LinkItem>
  )
}

const sharedStyle = css`
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  
  svg {
    color: ${colors.gray2};
    width: 32px;
    height: 32px;
  }
  
  &:active {
    svg {
      color: ${colors.primary};
    }
  }
`

const LinkItem = styled(NavLink)`
  ${sharedStyle}
  
  &.active {
    svg {
      color: ${colors.primary};
    }
  }
`

export default FooterTabItem

출처 링크

profile
데이터 분석가 준비 중입니다 (티스토리에 기록: https://cherylog.tistory.com/)

0개의 댓글