我有这个组件:
class DashboardPage extends Component {
constructor(props) {
super(props);
this.state = {
loading: true,
shownPage: ActiveDeals,
error: false,
errorDetails: null,
activeIcon: "Home"
};
}
componentDidMount() {
//
}
setShownPage = (name, iconName) => () => {
this.setState({ shownPage: name, activeIcon: iconName });
};
getIconColor = () => {
// could I call this from the Home component and check its name? Or know the caller?
return "primary";
};
render() {
const { classes } = this.props;
const menuItems = (
<List>
<ListItem className={classNames(classes.listItem)} button onClick={this.setShownPage(ActiveDeals, "Home")}>
<ListItemIcon className={classNames(classes.listItemIcon)}>
<Home color={this.state.activeIcon === "Home" ? "primary" : "secondary"} />
</ListItemIcon>
</ListItem>
<ListItem className={classNames(classes.listItem)} button onClick={this.setShownPage(UpcomingDates, "CalendarToday")}>
<ListItemIcon className={classNames(classes.listItemIcon)}>
<CalendarToday color={this.state.activeIcon === "CalendarToday" ? "primary" : "secondary"} />
</ListItemIcon>
</ListItem>
<ListItem className={classNames(classes.listItem)} button onClick={this.setShownPage(DealsPipeline, "FilterList")}>
<ListItemIcon className={classNames(classes.listItemIcon)}>
<FilterList color={this.state.activeIcon === "FilterList" ? "primary" : "secondary"} />
</ListItemIcon>
</ListItem>
</List>
);
return (
<MainFrame
route={this.props.match.url}
title={this.state.shownPage.title}
menuItems={menuItems}
open={this.state.open}
topRightFeature={this.state.shownPage.topRightFeature}
>
<this.state.shownPage />
<div>Primary color is {this.props.theme.palette.primary.main}</div>
</MainFrame>
);
}
}
export default withStyles(styles, { withTheme: true })(DashboardPage);
...我习惯于在后端语言中使用nameof()
和type()
来知道给定实例的名称。在React中,我尚未找到实现此目的的方法。
我不是基于状态来设置图标颜色(它使用硬编码的字符串,难),而是想要一种实用的方法来遍历dom树以找到相对的子代,或者只知道调用图标的名称的方法getIconColor
方法,以便可以将其与活动状态进行比较。
在使用“知道”例如被调用的函数的组件时,组件是否可以设置属性? Home
?
答案 0 :(得分:1)
如果将函数绑定在使用该函数的组件中,则可以获得调用者的身份。这仅在类组件中有效。
类似这样的东西:
class Apple extends React.Component {
constructor(props) {
super(props);
this.getName = props.getName.bind(this);
}
render() {
return <div>I am an {this.getName()}</div>;
}
}
class Banana extends React.Component {
getName() {
return this.constructor.name;
}
render() {
return (
<div className="App">
<Apple getName={this.getName} />
</div>
);
}
}
答案 1 :(得分:1)
我认为您正在尝试以一种错过React的声明能力和组件组合提供的可能性的方式来解决此问题。列表项之间的代码重复恳求引入另一个组件:
const listItemStyles = {
listItem: {
/* whatever styles you need */
},
listItemIcon: {
/* whatever styles you need */
}
};
const DashboardListItem = withStyles(listItemStyles)(
({ Page, Icon, ShownPage, classes, setShownPage }) => {
return (
<ListItem
className={classes.listItem}
button
onClick={() => setShownPage(Page)}
>
<ListItemIcon className={classes.listItemIcon}>
<Icon color={ShownPage === Page ? "primary" : "secondary"} />
</ListItemIcon>
</ListItem>
);
}
);
然后您的menuItems
变为:
const menuItems = [
{ Page: ActiveDeals, Icon: Home },
{ Page: UpcomingDates, Icon: CalendarToday },
{ Page: DealsPipeline, Icon: FilterList }
];
const mappedMenuItems = menuItems.map((menuItem, index) => (
<DashboardListItem
key={index}
{...menuItem}
ShownPage={this.state.shownPage}
setShownPage={this.setShownPage}
/>
));
完整代码如下:
import React, { Component } from "react";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import ListItemIcon from "@material-ui/core/ListItemIcon";
import { withStyles } from "@material-ui/core/styles";
import Home from "@material-ui/icons/Home";
import CalendarToday from "@material-ui/icons/CalendarToday";
import FilterList from "@material-ui/icons/FilterList";
const styles = {};
const ActiveDeals = () => {
return <div>ActiveDeals Page!</div>;
};
const UpcomingDates = () => {
return <div>UpcomingDates Page!</div>;
};
const DealsPipeline = () => {
return <div>DealsPipeline Page!</div>;
};
const listItemStyles = {
listItem: {
/* whatever styles you need */
},
listItemIcon: {
/* whatever styles you need */
}
};
const DashboardListItem = withStyles(listItemStyles)(
({ Page, Icon, ShownPage, classes, setShownPage }) => {
return (
<ListItem
className={classes.listItem}
button
onClick={() => setShownPage(Page)}
>
<ListItemIcon className={classes.listItemIcon}>
<Icon color={ShownPage === Page ? "primary" : "secondary"} />
</ListItemIcon>
</ListItem>
);
}
);
const menuItems = [
{ Page: ActiveDeals, Icon: Home },
{ Page: UpcomingDates, Icon: CalendarToday },
{ Page: DealsPipeline, Icon: FilterList }
];
class DashboardPage extends Component {
constructor(props) {
super(props);
this.state = {
shownPage: ActiveDeals
};
}
setShownPage = page => {
this.setState({ shownPage: page });
};
render() {
const mappedMenuItems = menuItems.map((menuItem, index) => (
<DashboardListItem
key={index}
{...menuItem}
ShownPage={this.state.shownPage}
setShownPage={this.setShownPage}
/>
));
return (
<div>
<List>{mappedMenuItems}</List>
<this.state.shownPage />
<div>Primary color is {this.props.theme.palette.primary.main}</div>
</div>
);
}
}
export default withStyles(styles, { withTheme: true })(DashboardPage);
这是一个可行的示例: