728x90
반응형
vite 환경
import svgr from 'vite-plugin-svgr';
vite.config.ts에 svgr() 추가함
이거 안 쓰면 컴포넌트 감싸서 가져와야 됨

import { Suspense, lazy, memo } from 'react';
import Loading from './Loading';
import { IconProps } from './types';
import S from './styles';
const Icon = memo(
({
fileName,
alt = 'image',
width = '100%',
height = '100%',
handleClick,
}: IconProps) => {
const LazyComponent = lazy(() =>
import(`./elements/${fileName}.svg`)
.then((module) => ({
default: () => (
<img
onClick={handleClick}
src={module.default}
style={{ width, height }}
/>
),
}))
.catch(() => ({
default: () => (
<S.FailImg size={{ width, height }}>
{alt} <br />
이미지
</S.FailImg>
),
})),
);
return (
<Suspense fallback={<Loading width={width} height={height} />}>
<LazyComponent />
</Suspense>
);
},
);
export default Icon;
import styled, { keyframes } from 'styled-components';
const Loading = ({ width = '100%', height = '100%' }) => {
return (
<LoadingSpinner size={{ width, height }}>
<Spinner className="spinner"></Spinner>
</LoadingSpinner>
);
};
export default Loading;
const LoadingSpinner = styled.div<{ size: { width: string; height: string } }>`
display: flex;
justify-content: center;
align-items: center;
width: ${({ size }) => size.width};
height: ${({ size }) => size.height};
`;
const spin = keyframes`
to {
transform: rotate(360deg);
}
`;
const Spinner = styled.div`
border: 4px solid rgba(0, 0, 0, 0.1);
width: 50%;
height: 50%;
border-radius: 50%;
border-left-color: #09f;
animation: ${spin} 1s ease infinite;
`;
아이콘을 로딩하기 전 스피너, 아이콘 로딩 실패시 보여줄 수 있는 UI의 장점도 있지만
무엇보다 icon 을 모두 저 컴포넌트 안에서 해결할 수 있어서 좋은 거 같다
icon 쓸 때마다 이름만 넘겨주면 import도 저 컴포넌트 안에서 동적으로 가능하고...
관심사 잘 모은 거 같아서 뿌듯쓰
728x90
반응형
'TIL' 카테고리의 다른 글
타입스크립트의 추론 (1) | 2024.07.20 |
---|---|
새로 나온 hook useFormStatus 등 리액트 동향 살펴보기 (0) | 2024.07.02 |
vite와 swc (1) | 2024.06.30 |
ts 브랜딩 타입 (태그드 타입) vs enum vs 리터럴 (0) | 2024.06.28 |
jest (0) | 2024.06.26 |
댓글