Reactjs 是否可以通过从其道具之一调用函数来获取嵌套的内部React组件的名称?

Reactjs 是否可以通过从其道具之一调用函数来获取嵌套的内部React组件的名称?,reactjs,material-ui,Reactjs,Material Ui,我有这个部分: class DashboardPage extends Component { constructor(props) { super(props); this.state = { loading: true, shownPage: ActiveDeals, error: false, errorDetails: null, activeIcon: "Home" }; } compo

我有这个部分:

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);
类仪表板页扩展组件{
建造师(道具){
超级(道具);
此.state={
加载:对,
shownPage:ActiveDeals,
错误:false,
errorDetails:null,
活动图标:“主页”
};
}
componentDidMount(){
//
}
setShownPage=(名称,图标名)=>()=>{
this.setState({shownPage:name,activeIcon:iconName});
};
getIconColor=()=>{
//我可以从Home组件调用它并检查它的名称吗?或者知道调用方吗?
返回“主”;
};
render(){
const{classes}=this.props;
常量菜单项=(
);
返回(
主色是{this.props.theme.palete.Primary.main}
);
}
}
使用样式导出默认值(样式,{withTheme:true})(仪表板页面);
。。。我习惯于在后端语言中使用
nameof()
type()
来了解给定实例的名称。在React中,我还没有找到一种方法来做到这一点

我不希望基于状态设置图标颜色(使用硬编码字符串,糟糕),而是希望有一种功能性的方法来遍历dom树以查找相关子级,或者只知道调用
getIconColor
方法的图标名称,以便将其与活动状态进行比较


组件在使用“知道”从中调用的函数(例如,
Home
)时,是否有任何方法可以设置属性?

如果在使用该函数的组件中绑定该函数,则可以获取调用方的标识。这只能在类组件中工作

大概是这样的:

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);
类Apple扩展React.Component{ 建造师(道具){ 超级(道具); this.getName=props.getName.bind(this); } render(){ return我是一个{this.getName()}; } } 类。组件{ getName(){ 返回this.constructor.name; } render(){ 返回( ); }
}我认为您试图以一种忽略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>
    );
  }
);
完整代码如下所示:

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);
import React,{Component}来自“React”;
从“@material ui/core/List”导入列表;
从“@material ui/core/ListItem”导入ListItem;
从“@material ui/core/ListItemIcon”导入ListItemIcon;
从“@material ui/core/styles”导入{withStyles}”;
从“@material ui/icons/Home”导入主页;
从“@material ui/icons/CalendarToday”导入CalendarToday;
从“@material ui/icons/FilterList”导入过滤器列表;
常量样式={};
const ActiveDeals=()=>{
返回ActiveDeals页面!;
};
常数更新日期=()=>{
返回更新日期页面!;
};
const dealsipeline=()=>{
返回交易列表页面!;
};
常量listItemStyles={
列表项:{
/*你需要什么款式都行*/
},
listItemIcon:{
/*你需要什么款式都行*/
}
};
const DashboardListItem=带有样式(listItemStyles)(
({Page,Icon,ShownPage,classes,setShownPage})=>{
返回(
设置显示页面(第页)}
>
);
}
);
常量菜单项=[
{Page:ActiveDeals,Icon:Home},
{页面:更新日期,图标:CalendarToday},
{Page:dealsipeline,Icon:FilterList}
];
类DashboardPage扩展组件{
建造师(道具){
超级(道具);
此.state={
shownPage:ActiveDeals
};
}
setShownPage=页面=>{
this.setState({shownPage:page});
};
render(){
const mappedMenuItems=menuItems.map((menuItem,index)=>(
));
返回(
{mappedMenuItems}
主色是{this.props.theme.palete.Primary.main}
);
}
}
使用样式导出默认值(样式,{withTheme:true})(仪表板页面);
下面是一个工作示例:


谢谢,我不知道
这个.constructor.name
。但是,只有在我自己定义组件的情况下才能使用它吗?当我在Material UI组件上尝试它时,我只得到了
函数
。感谢您的回答。我不得不在
地图
结果中添加一个
,并从onClick中删除
()=>
,但效果很好。我已经更新了答案,添加了这个键——好的捕获。在我的代码中,我已经删除了
setShownPage
定义中的额外curry,因此
()=>
onClick
中是必需的。