代码之家  ›  专栏  ›  技术社区  ›  JacobIRR

是否可以通过从某个属性调用函数来获取嵌套的内部react组件的名称?

  •  1
  • JacobIRR  · 技术社区  · 6 年前

    我有这个组件:

    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() 在后端语言中知道给定实例的名称。在反应方面,我还没有找到一种方法来做到这一点。

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

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

    2 回复  |  直到 6 年前
        1
  •  1
  •   Ryan Cogswell    6 年前

    我认为您试图以一种忽略了反应的声明性能力和组件组合提供的可能性的方式来解决这个问题。列表项之间的代码重复要求引入另一个组件:

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

    下面是一个工作示例:

    Edit DashboardPage

        2
  •  1
  •   Max    6 年前

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

    像这样:

    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