我在数据库中保留了一个菜单列表,同时还保留了图标。挑战在于Icons是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>
);
};
由于XSS等安全漏洞,我不建议您进行任何类型的解析。
我可能错了,但如果你从数据库加载图标,比如:
<homeicon/>
记住,用户组件必须大写,顺便说一句,在使用它们之前,你还需要导入图标,所以,更好的方法是:
- 不要将整个组件存储在数据库中,只需存储图标名称即可
- 使用官方文档中的图标组件,只需将图标名称作为子项传递即可
导航到以下部分以获取更多详细信息:图标(字体图标(
- https://mui.com/material-ui/icons/
这是整个实现的一个基本示例:
import Icon from '@mui/material/Icon';
const IconList = ({ icons = [] }) => {
return (
<>
{icons.map({name} => <Icon>{name}</Icon>)}
</>
);
};
通过这种方式,您还可以从官方材料ui文档中存储诸如color、sx、fontSize等道具,并将它们存储在数据库中,以使组件更易于升级。