배경
1) next에서 svg파일을 Image태그로 감싸서 사용하고 있었다.
2) 그러던 중 색상을 props에 따라 변경해줘야하는 상황이 발생했다. (isClick에 따라서 색상 변경)
3) 조건에 따라 다른 색을 가진 svg파일을 렌더링하는 방법도 있었겠지만 색상으로 컨트롤 해보고 싶었다.
검색 결과..
svgr을 통해 svg 파일을 컴포넌트처럼 사용할 수 있다는 걸 알았다.
사용 방법
1. 설치
yarn add -D @svgr/webpack
2. next.config.js 수정
/** @type {import('next').NextConfig} */
const nextConfig = {
// 웹팩을 통해 svg 파일을 리액트 컴포넌트로 변환하는 설정이다
webpack: (config) => {
config.module.rules.push({
test: /\.svg$/,
use: ['@svgr/webpack'],
});
return config;
},
reactStrictMode: true,
};
module.exports = nextConfig;
3. svg 파일 수정
나는 색상을 변경하고 싶었기에, fill에 currentColor을 넘겨주는 형식으로 사용했음. 참고로 path 안의 fill도 current로 수정해줘야한다.
<svg width="28" height="30" viewBox="0 0 28 30" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path d="M24.5 3H23V0H20V3H8V0H5V3H3.5C1.835 3 0.515 4.35 0.515 6L0.5 27C0.5 28.65 1.835 30 3.5 30H24.5C26.15 30 27.5 28.65 27.5 27V6C27.5 4.35 26.15 3 24.5 3ZM24.5 27H3.5V12H24.5V27ZM24.5 9H3.5V6H24.5V9ZM9.5 18H6.5V15H9.5V18ZM15.5 18H12.5V15H15.5V18ZM21.5 18H18.5V15H21.5V18ZM9.5 24H6.5V21H9.5V24ZM15.5 24H12.5V21H15.5V24ZM21.5 24H18.5V21H21.5V24Z"
fill="current"/>
</svg>
4. svgr을 styled component와 함께 사용해보자
Next.js에서 svg에 styled-components 적용
svgr 설치 > yarn add -D @svgr/webpack next.config.js 수정 svg 파일 수정 width, height, fill, stroke 등 변경을 원하는 속성값을 current로 수정 styled-components 적용 & 사용 결과 Reference https://react-svgr.com/docs/next/ h...
velog.io
위 블로그를 참고했다.
//import svg
import { MoneyIcon } from 'asset';
// 컴포넌트 사용
return (
<MoneySvg
isClick={clickedId === 3}
onClick={() => handleClick(3)}
src={MoneyIcon}
alt="입금관리 아이콘"></MoneySvg>
)
// styled component
const MoneySvg = styled(MoneyIcon)<Props>`
cursor: pointer;
stroke: ${({ isClick }) => (isClick ? theme.colors.mainColor : theme.colors.gray)};
`;
생각보다 직관적이다.
그냥 svg파일을 import 해서, 해당 svg파일을 div, Image처럼 styled component의 태그로 사용하면 된다.
해당 태그를 styled component로 만들어, 그것을 쓰면 되는 것!
이렇게 하면 svg태그의 style 중 border, fill, ..등의 요소를 내맘대로 변경할 수 있다.
나는 클릭 될 때마다 색상값을 변경되게 끔 만들어놨다.
마무리
음하하.. full code는 아래와 같다.
이 코드엔 클릭될 수 있는 요소들이 여러 개 있을 때 - 클릭된 state를 관리하는 내용도 포함되어있다.
도움이 되기를 바라며 첨부해본당.
import React, { useEffect, useState } from 'react';
import { ClassListIcon, CalendarIcon, MoneyIcon } from 'asset';
import Image from 'next/image';
import styled from 'styled-components';
import theme from '@src/styles/theme';
interface Props {
isClick?: boolean;
onClick?: () => void;
}
const Footer = () => {
// const [isClicked, setIsClicked] = useState<boolean>(false);
const [clickedId, setClickedId] = useState<number>(-1);
const handleClick = (index: number) => {
setClickedId(index);
};
useEffect(() => {
setClickedId(clickedId);
}, [clickedId]);
return (
<Wrapper>
<ClassListSvg
isClick={clickedId === 1}
onClick={() => handleClick(1)}
src={ClassListIcon}
alt="진행 중인 과외 아이콘"></ClassListSvg>
<CalenderSvg
isClick={clickedId === 2}
onClick={() => handleClick(2)}
src={CalendarIcon}
alt="캘린더 아이콘"></CalenderSvg>
<MoneySvg
isClick={clickedId === 3}
onClick={() => handleClick(3)}
src={MoneyIcon}
alt="입금관리 아이콘"></MoneySvg>
</Wrapper>
);
};
export default Footer;
const Wrapper = styled.div`
position: fixed;
bottom: 0;
overflow-x: hidden;
display: flex;
justify-content: space-around;
align-items: center;
z-index: 3;
width: 37.5rem;
height: 6rem;
background-color: ${theme.colors.white};
border-radius: 2rem 2rem 0rem 0rem;
`;
const CalenderSvg = styled(CalendarIcon)<Props>`
cursor: pointer;
color: ${({ isClick }) => (isClick ? theme.colors.mainColor : theme.colors.gray)};
`;
const ClassListSvg = styled(ClassListIcon)<Props>`
cursor: pointer;
color: ${({ isClick }) => (isClick ? theme.colors.mainColor : theme.colors.gray)};
`;
const MoneySvg = styled(MoneyIcon)<Props>`
cursor: pointer;
stroke: ${({ isClick }) => (isClick ? theme.colors.mainColor : theme.colors.gray)};
`;
'Web > React' 카테고리의 다른 글
리액트쿼리 react-query 도입기 | 기본 개념 공식문서 톺아보기 - useQuery, useMutation, invalidateQueries (0) | 2023.07.06 |
---|