(주의!!)
React.cloneElement 메서드는 리액트 요소에서만 적용되므로
SVG가 직접 JSX로 사용되고 있으면 해당 방법을 사용할 수 없다.
프로젝트에서 item.icon -> 리액트 컴포넌트로서 사용하고 있었다.
SVG 컴포넌트를 직접 렌더링하는 방식으로 사용하고 있었다.리액트 컴포넌트에만 유효한 React.cloneElement를 사용할 수 있다.
아이콘을 적용하는 부분에서 i
import { ReactComponent as ~~ } from './경로';
이렇게 사용이 가능하다.
아이콘을 특정 상태에 따라 스타일을 변경하여 렌더링을 한다고 가정하자.
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> )}