Is it possible to get the name of a nested, inner React Component by calling a function from one of its props?

半城伤御伤魂 提交于 2019-12-07 02:02:28

I think you're trying to solve this in a way that misses out on the declarative power of React and the possibilities that component composition provides. The code duplication between the list items is begging for another component to be introduced:

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>
    );
  }
);

Then your menuItems becomes:

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}
  />
));

With the full code looking like this:

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);

Here's a working example:

You can get the identity of the caller if you bind the function in the component where it is used. This would work only in a class component.

Something like this:

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>
    );
  }
}

https://codesandbox.io/s/247lpxl4j0

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!