Я пытаюсь сгенерировать свой блок навигации из JSON, и у меня все работает, используя только компоненты, но я делаю рефакторинг для функций, где могу, для повышения производительности (и чтобы узнать больше о React и Javascript). Если я оставляю DrawerLink в качестве отдельного компонента, тогда все работает как положено, но если я пытаюсь передать renderLink из PopulateDrawer (родительский компонент), он ломается и выдает ошибку, что ничего не было возвращено из render.
Насколько я могу судить, я следую инструкциям отсюда https://reactjs.org/docs/handling-events.html и здесь https://material -ui.com / demos / buttons / , но это не работает. Это потому, что я прохожу через компонент, а не функцию? Это где компоненты высшего порядка вступают в игру? Я видел, как они упоминались, но пока не понял, как правильно их использовать.
import React from 'react';
import Divider from '@material-ui/core/Divider';
import ExpandLess from '@material-ui/icons/ExpandLess';
import ExpandMore from '@material-ui/icons/ExpandMore';
import ListItem from '@material-ui/core/ListItem';
import ListItemText from '@material-ui/core/ListItemText';
import { Link } from 'react-router-dom';
import { List, Collapse } from '@material-ui/core';
class DrawerLink extends React.Component {
renderLink = itemProps => <Link to={this.props.link} {...itemProps} />;
render() {
const { display } = this.props;
return (
<ListItem button component={this.renderLink}>
<ListItemText primary={display} />
</ListItem>
);
}
}
function ProcessJSON(props) {
const {
data,
groupDrawers,
updateGroupDrawer,
renderLink
} = props;
return (
Object.keys(data).map(key => {
if (data[key] === "divider") {
return (
<Divider key={key} />
)
}
else {
let childData = data[key];
let listDetected = false;
Object.keys(childData).map(key => {
if (key == "list") {
listDetected = true;
}
})
if (listDetected === false) {
return (
// <DrawerLink
// key={childData.display}
// display={childData.display}
// link={childData.link}
// renderLink={renderLink} />
<ListItem key={childData.display} button component={(e) => renderLink(childData.link)}>
<ListItemText primary={childData.display} />
</ListItem>
)
}
else {
return (
<React.Fragment key={childData.display}>
<ListItem button onClick={() => updateGroupDrawer(childData.display, !groupDrawers[childData.display])}>
<ListItemText primary={childData.display} />
{groupDrawers[childData.display] ? <ExpandLess /> : <ExpandMore />}
</ListItem>
<Collapse
in={groupDrawers[childData.display]}
timeout="auto" unmountOnExit >
<List component="div">
<ProcessJSON
data={childData.list}
groupDrawers={groupDrawers}
updateGroupDrawer={updateGroupDrawer} />
</List>
</Collapse>
</React.Fragment>
)
}
}
})
)
}
class PopulateDrawer extends React.Component {
componentDidMount() {
const groupDrawers = {...this.state.groupDrawers, ...this.props.groupDrawers};
this.setState({ groupDrawers });
};
state = {
groupDrawers: {}
};
updateGroupDrawer = (display, open) => {
const groupDrawers = {...this.state.groupDrawers};
groupDrawers[display] = open;
this.setState({ groupDrawers });
};
renderLink = (link) => {
<Link to={link} />
};
render() {
const {
data,
} = this.props;
return (
<ProcessJSON
data={data}
groupDrawers={this.state.groupDrawers}
updateGroupDrawer={this.updateGroupDrawer}
renderLink={this.renderLink}/>
)
}
}
export default PopulateDrawer;
редактировать, добавив, что код BLOB-объекта JSON выполняется для:
"data": {
"nav1": {
"display": "Home",
"link": "/"
},
"nav2": {
"display": "Templates",
"link": "templates"
},
"nav3": "divider",
"nav4": {
"display": "Test",
"list": {
"nav1": {
"display": "Home",
"link": "/"
},
"nav2": {
"display": "Templates",
"link": "templates"
}
}