오류 해결) svg 아이콘 렌더링 문제 React.cloneElement()

지원·2024년 4월 7일
0

오류 해결

목록 보기
5/5
post-thumbnail

svg 이이콘 사용하는 경우 렌더링 문제

  1. React.cloneElement 메서드의 사용

(주의!!)
React.cloneElement 메서드는 리액트 요소에서만 적용되므로
SVG가 직접 JSX로 사용되고 있으면 해당 방법을 사용할 수 없다.

프로젝트에서 item.icon -> 리액트 컴포넌트로서 사용하고 있었다.
SVG 컴포넌트를 직접 렌더링하는 방식으로 사용하고 있었다.

리액트 컴포넌트에만 유효한 React.cloneElement를 사용할 수 있다.

아이콘을 적용하는 부분에서 i

import { ReactComponent as ~~ } from './경로';

이렇게 사용이 가능하다.

React.cloneElement()

아이콘을 특정 상태에 따라 스타일을 변경하여 렌더링을 한다고 가정하자.

Recat.cloneElement()를 사용해서
아이콘을 복제하고 새로운 요소로 만들어서 새로운 스타일 적용이 가능하다.

React 요소를 직접 수정할 수 없는 React의 불변성 원칙을 유지하면서,
기존 요소를 기반으로 새로운 요소를 만드는 과정을 단순화할 수 있다.

조건에 따라 컴포넌트의 특정 props를 쉽게 조정 가능하다.

예)

const Icon = item.icon;
const itemIcon = item.icon ? <Icon sx={{ fontSize: drawerOpen ? '1rem' : '1.25rem' }} /> : false;

const itemIcon에서 Icon에 직접 스타일을 지정하지 않고?

아래의 코드처럼
{React.cloneElement(Icon, { style: { fontSize: drawerOpen ? '1rem' : '1.25rem' } })}
으로 새로운 요소로 복제한 다음 스타일을 적용해야 한다.

    return (
        <ListItemButton
            {...listItemProps}
            // disabled={item.disabled}
            onClick={() => itemHandler(item.path)}
            selected={isSelected}
            sx={{
                zIndex: 1201,
                pl: drawerOpen ? `${level * 28}px` : 1.5,
                py: !drawerOpen && level === 1 ? 1.25 : 1,
                ...(drawerOpen && {
                    '&:hover': {
                        bgcolor: 'primary.lighter'
                    },
                    '&.Mui-selected': {
                        bgcolor: 'primary.lighter',
                        borderRight: `2px solid ${theme.palette.primary.main}`,
                        color: iconSelectedColor,
                        '&:hover': {
                            color: iconSelectedColor,
                            bgcolor: 'primary.lighter'
                        }
                    }
                }),
                ...(!drawerOpen && {
                    '&:hover': {
                        bgcolor: 'transparent'
                    },
                    '&.Mui-selected': {
                        '&:hover': {
                            bgcolor: 'transparent'
                        },
                        bgcolor: 'transparent'
                    }
                })
            }}

            {Icon && (
                <ListItemIcon
                    sx={{
                        minWidth: 28,
                        color: isSelected ? iconSelectedColor : textColor,
                        ...(!drawerOpen && {
                            borderRadius: 1.5,
                            width: 36,
                            height: 36,
                            alignItems: 'center',
                            justifyContent: 'center',
                            '&:hover': {
                                bgcolor: 'secondary.lighter'
                            }
                        }),
                        ...(!drawerOpen &&
                            isSelected && {
                                bgcolor: 'primary.lighter',
                                '&:hover': {
                                    bgcolor: 'primary.lighter'
                                }
                            })
                    }}

                    {/*{itemIcon}*/}
                    {React.cloneElement(Icon, { style: { fontSize: drawerOpen ? '1rem' : '1.25rem' } })}
                </ListItemIcon>
            )}

0개의 댓글

관련 채용 정보