Давайте создадим ящик / панель навигации, которая получает список объектов предметов и затем рендерит рекурсивным способом. Прежде всего, определите структуру, как вы уже сделали в menuItems
, я ее немного изменю:
const items = [
{name: 'Shallow Item', path='/', type:'shallow'},
{
name: 'Nested',
type: 'nested',
items:[
{name: 'Shallow again', path='/nestedpath'}
]
}
]
Теперь у нас есть два элемента в вашем списке, один из которых является простым мелким элементом, который не содержит вложенных опций, а второй является вложенным элементом, который содержит список мелких элементов.
Теперь нам нужно построить или два основных компонента: <NestedItem>
и <ShallowItem>
. Они должны выглядеть примерно так:
const ShallowItem = ({item, onClick}) =>(
<ListItem
component={Link}
to={item.path || #}
onClick={onClick ? onClick : ()=>{} }
>
<ListItemText primary={item.name}/>
{Boolean(nested) &&
<Icon>
{collapsed ? 'arrow_drop_up' : 'arrow_drop_down'}
</Icon>
}
</ListItem>
)
Обратите внимание, что свойства onClick
и to
(реакция-маршрутизатор) имеют свои значения, условно приписанные, потому что мы собираемся использовать один и тот же компонент для рендеринга первого слоя и списка NestedItem
, как это:
const NestedItem = ({ item }) => {
const [collapsed, toggler] = useState(false)
const classes = useStyles()
return (
<div>
<ShallowItem
item={{ icon: item.icon, title: item.title }}
nested
collapsed={collapsed}
onClick={() => toggler(!collapsed)}
/>
<Collapse in={collapsed}>
<List component='div'>
{item.items.map(item => (
<ShallowItem item={item} key={item.title}/>
))}
</List>
</Collapse>
</div>
)}
Ну вот, вы схватили идею? Единственный действительно визуализируемый компонент - это ShallowItem
, потому что NestedItem
- это просто набор мелких предметов. Поэтому мы сначала визуализируем неглубокий элемент, который открывает контейнер свертывания, содержащий подсписок более мелких элементов. Единственное, что нам нужно сделать сейчас, это проверить, есть ли у элемента подэлементы, регистр положительный, NestedItem
, в противном случае - ShallowItem
. Эта функция:
const renderItems = items =>{
for(let item of items){
switch(item.type){
case 'nested': return <NestedItem item={item} />
case 'shallow' : return <ShallowItem item={item} />
}
}
}
Теперь у вас есть рекурсивный способ рендеринга вложенных элементов, вам нужно только стилизовать один компонент, и сделать глубину теперь довольно легко. Мы используем это решение в нашей компании, и оно работает как шарм.