Как визуализировать компонент React в себе, рекурсивным образом
У меня есть компонент, скажем, List Component. Компонент List может отображать элементы через компонент ListItem. Который может быть легко достигнут с чем-то вроде ниже
import React from 'react';
import ListItem from '../list-item/list-item';
class List extends React.Component {
renderListItems() {
return this.props.items.map(item => <ListItem item={item} />)
}
render(){
return (
<div className="list">{this.renderListItems()}</div>
)
}
}
а также
import React from 'react';
class ListItem extends React.Component {
render(){
return (
<div className="list-item">Name: {this.props.item.name}</div>
)
}
}
Теперь, в этом случае, если элементы списка могут иметь родительские дочерние элементы внутри них, то один элемент списка может дополнительно отобразить больше элементов списка, как я могу визуализировать компонент ListItem из самого себя. Ниже приводится дерево рендеринга, которое я ищу, а также состояние моих данных
List
- ListItem
- ListItem
- ListItem
- ListItem
- ListItem
редактировать
Я думаю, что правильная структура будет чем-то вроде этого
List
- ListItem
- List
- ListItem
- ListItem
- ListItem
- ListItem
Но это, конечно же, создаст круговую зависимость между компонентами List и ListItem, будет ли это проблемой?
Ответы
Ответ 1
Вы должны абстрагировать логику рендеринга в отдельный метод, который вы можете вызывать рекурсивно из метода "рендеринга":
import List from 'somewhere';
class RecursiveItems extends React.PureComponent {
constructListItem = (item) => {
if (item.nestedItems) {
return (
<List key={item.key}>
{item.nestedItems.map(this.constructListItem)}
</List>
)
} else {
return <ListItem key={item.key} item={item} />
}
}
render() {
const { listItems } = this.props
return (
<List>
{listItems.map(this.constructListItem)}
</List>
)
}
}
export default RecursiveItems
Полностью непроверенный код, но он должен дать идею.
Ответ 2
Использование функциональных компонентов:
//List.js
import React from 'react';
import ListItem from '../your_path/ListItem';
export default function List({items}) {
return(
<div className="list">
{
items.map(item => {
if(item.name){
return <ListItem item={item} />
}
return <List items={item} />
})
}
</div>
);
}
//ListItem.js:
import React from 'react';
export default function ListItem({item}){
return (
<div className="list-item">Name: {item.name}</div>
)
}
Не проверял, но я думаю, что это должно работать..
Ответ 3
Таким образом, рекурсия чище
const Asterics= ({i}) => [
<b>*</b>,
i>0 && <RAsterics i={i-1}/>
]
const RAsterics = (props)=><Asterics {...props}/>
export default Asterics