프로그래머스 웹페이지를 클론하면서 여러 이미지를 활용해야하는 부분이 있었다.
처음에는 스타일드 컴포넌트 아이콘 라이브러리를 활용하려 했지만 내가 아는 선에서는 스타일드 컴포넌트 아이콘을 사용하면 코드가 너무 비효율적이어질 것 같은 느낌..
일단 필요한 이미지들의 svg 파일들을 다운받긴했는데.. 그 당시에는 이미지 태그의 소스로 사용하는 법밖에 몰랐던 svg 초짜.. svg를 제대로 사용해보자 라는 생각으로 대략 3일을 내내 이 로직을 짜고 svg 파일을 효율적으로 활용하는 법에 대해 매달려 있었다..
background-color
는 넣을 수 있지만 실제 색깔제어 못한다는 한계점에 봉착했다. 처음에는 호버되면 색깔 바뀌는 기능 없는 척ㅇㅅㅇ; 하고 싶었지만 svg 널 뽀개주겠어.. 하고 리팩토링을 시작<Languages value={questionData.programming_language}>
{questionData &&
questionData.programming_language.map((lang, index) => (
<LanguageIcons key={index}>
<ToolTip name={lang.name} hoverIcon={hoverIcon}>
{lang.name}
</ToolTip>
<LanguageIcon
value={lang.id}
name={lang.name}
alt={lang.name}
src={`/image/languageImgSrc/${
lang.name === 'C#' ? 'CSharp' : lang.name
}.svg`} // ⭐ 그저.. img태그의 src 속성으로 제어해주려했던 어리석은 과거
onMouseEnter={() => {
setHoverIcon(lang.name);
}}
onMouseLeave={() => {
setHoverIcon();
}}
/>
</LanguageIcons>
))}
</Languages>
import { ReactComponent as 아이콘컴포넌트명 } from ‘경로’
<svg>
태그 내에서 변경 해주고싶은 스타일 속성들은 모두 current 값으로 바꿔준다. (width, height, fill 등을 current로 바꿔주었다!)<svg>
태그 하위에 path 태그가 여러개가 있고 fill 속성이 각각 들어있는 것이 있기 때문에 fill 값 모두 확인하고 넣어주자. 그렇지 않으면 그림 중 한곳만 띠용하게 다른 색깔이 들어가게된다.const langData = questionData.programming_language.map(lang => lang.name);
console.log(langData) // ["C","C++","Java"]
display:none
이 되도록 했더니 아래와 같이 매우 비효율적인 코드가 탄생했다.. display: ${props =>
props.langData.includes(props.name) ? 'inline-flex' : 'none'};
//스타일드 컴포넌트로 langData배열에 그 값이 있으면 렌더 아니면 안보이도록 스타일링
🤯 어떻게 리팩토링 할 수 있을지 고민 🤯
반복되는 코드들과 하드코딩한 코드들이 많아서 어떻게 줄일 수 있을까.. 맘같아선 위에서 도출한langData
배열을 활용해서 맵을 돌리고 싶지만 svg 파일을 컴포넌트로 import해주었기 때문에 컴포넌트태그를 쓸 때 조건부로 줄 수 없었다...
갓 은정님의 피드백으로 리팩토링 할 수 있었다!!!
리팩토링 과정을 요약해서 말하자면,
<svg>
태그를 리턴하도록하는 함수를 value값으로 가지는 객체를 만들어준다
const languageSvgObj = {
C: () => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 128 128"
width="current"
height="current"
>
<path
fill="current"
d="M117.5 33.5l.3-.2c-.6-1.1-1.5-2.1-2.4-2.6l-48.3-27.8c-.8-.5-1.9-.7-3.1-.7-1.2 0-2.3.3-3.1.7l-48 27.9c-1.7 1-2.9 3.5-2.9 5.4v55.7c0 1.1.2 2.3.9 3.4l-.2.1c.5.8 1.2 1.5 1.9 1.9l48.2 27.9c.8.5 1.9.7 3.1.7 1.2 0 2.3-.3 3.1-.7l48-27.9c1.7-1 2.9-3.5 2.9-5.4v-55.8c.1-.8 0-1.7-.4-2.6zm-53.5 55c9.1 0 17.1-5 21.3-12.4l12.9 7.6c-6.8 11.8-19.6 19.8-34.2 19.8-21.8 0-39.5-17.7-39.5-39.5s17.7-39.5 39.5-39.5c14.7 0 27.5 8.1 34.3 20l-13 7.5c-4.2-7.5-12.2-12.5-21.3-12.5-13.5 0-24.5 11-24.5 24.5s11 24.5 24.5 24.5z"
/>
</svg>
'C#': () => (...)
.
.
.
return (
<LanguageSvgContainer hover={name === hoverIcon}>
{languageSvgObj[name]()} //⭐객체의 key 값으로 접근하여 함수를 호출해준다
</LanguageSvgContainer>
);
// 여기서 name,hoverIcon 이라는 props는 호버 시 툴팁 생성을 위해 상위 컴포넌트에서 받아주었다
//name (렌더링할 프로그래밍 언어를 문자열로 넘겨줌)
//hoverIcon(onMouseEnter 시, 해당 프로그래밍 언어를 hoverIcon 라는 state에 문자열로 저장)
위의 과정을 통해 배운 것 중 가장 중요한 것은 객체를 통해 재사용 가능한 함수 형태를 만들어주었고 그것을 활용해서 svg 이미지들을 효율적으로 사용해주었다는 것!
마지막방법같은경우 margin 같은 스타일은 어떻게 적용시켜야한가요?