Как преобразовать строку в узел/элемент React
Я храню список меню в своей базе данных, а вместе с ним и иконки. Проблема заключается в том, что значки являются значками MUI и сохраняются как элемент узла React. Например:<HomeIcon fontSize="small" />
Когда я визуализирую список меню, все выглядит великолепно, ПОМИМО значков, поскольку он отображает их как текст, а не как элементы React.
Я перепробовал так много вариантов, чтобы отобразить их как React, но не смог найти правильного решения.
Последнее, что я использовал, это Parse ('html-react-parser'), но безуспешно, поскольку он сохраняет элементы в нижнем регистре.
Это код разбора:
const icon = (item.icon ? parse(item.icon, {lowerCaseTags: false}) : "");
Но затем я получаю следующую ошибку:
Warning: The tag <homeicon> is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter.
at homeicon
at span
Это узел React, который я визуализирую:
<DashboardSidebarItem
active={partialMatch}
chip={item.chip}
depth={depth}
icon={icon}
info={item.info}
key={key}
open={partialMatch}
path={item.path}
title={item.title}
>
{renderNavItems({
depth: depth + 1,
items: item.children,
path
})}
</DashboardSidebarItem>
И это элемент DashboardSidebarItem:
export const DashboardSidebarItem = (props) => {
const {
active,
children,
chip,
depth,
icon,
info,
open: openProp,
path,
title,
...other
} = props;
const [open, setOpen] = useState(openProp);
const handleToggle = () => {
setOpen((prevOpen) => !prevOpen);
};
let paddingLeft = 24;
if (depth > 0) {
paddingLeft = 32 + 8 * depth;
}
// I NEED TO CONVERT IT TO REACT NATIVE
// Branch
if (children) {
return (
<ListItem
disableGutters
sx={{
display: 'block',
mb: 0.5,
py: 0,
px: 2
}}
{...other}>
<Button
endIcon={!open
? <ChevronRightIcon fontSize="small" />
: <ChevronDownIcon fontSize="small" />}
disableRipple
onClick={handleToggle}
startIcon={icon}
sx={{
color: active ? 'secondary.main' : 'neutral.300',
justifyContent: 'flex-start',
pl: `${paddingLeft}px`,
pr: 3,
textAlign: 'left',
textTransform: 'none',
width: '100%',
'&:hover': {
backgroundColor: 'rgba(255,255,255, 0.08)'
},
'& .MuiButton-startIcon': {
color: active ? 'secondary.main' : 'neutral.400'
},
'& .MuiButton-endIcon': {
color: 'neutral.400'
}
}}
>
<Box sx={{ flexGrow: 1 }}>
{title}
</Box>
{info}
</Button>
<Collapse
in={open}
sx={{ mt: 0.5 }}
>
{children}
</Collapse>
</ListItem>
);
}
// Leaf
return (
<ListItem disableGutters sx={{display: 'flex', mb: 0.5, py: 0, px: 2 }}>
<NextLink href={path} passHref >
<Button
component="a"
startIcon={icon}
endIcon={chip}
disableRipple
sx={{
backgroundColor: active && 'rgba(255,255,255, 0.08)',
borderRadius: 1,
color: active ? 'secondary.main' : 'neutral.300',
fontWeight: active && 'fontWeightBold',
justifyContent: 'flex-start',
pl: `${paddingLeft}px`,
pr: 3,
textAlign: 'left',
textTransform: 'none',
width: '100%',
'& .MuiButton-startIcon': {
color: active ? 'secondary.main' : 'neutral.400'
},
'&:hover': {
backgroundColor: 'rgba(255,255,255, 0.08)'
}
}}
>
<Box sx={{ flexGrow: 1 }}>
{title}
</Box>
{info}
</Button>
</NextLink>
</ListItem>
);
};
1 ответ
Я бы не рекомендовал вам выполнять какой-либо анализ из-за уязвимостей безопасности, таких как XSS.
Я могу ошибаться, но если вы загружаете значки из базы данных, например:
<homeicon/>
Помните, что пользовательские компоненты должны быть написаны с заглавной буквы, кстати, вам также необходимо импортировать значки перед их использованием, поэтому лучшим подходом будет:
- Вместо того, чтобы хранить в базе данных весь компонент, просто сохраните имя значка.
- Используйте компонент Icon из официальной документации и просто передайте имя значка в качестве дочернего элемента.
Перейдите к следующему разделу для получения более подробной информации: Значок (Значки шрифтов)
Это базовый пример всей реализации:
import Icon from '@mui/material/Icon';
const IconList = ({ icons = [] }) => {
return (
<>
{icons.map({name} => <Icon>{name}</Icon>)}
</>
);
};
Таким образом, вы также можете хранить реквизиты, такие как color, sx, fontSize и т. д., из официальной документации material-ui и хранить их в базе данных, чтобы сделать компонент более масштабируемым.