【问题标题】:access the theme from outside material-ui component从外部 material-ui 组件访问主题
【发布时间】:2018-05-13 18:44:30
【问题描述】:

我有一个使用标准深色主题的主题提供程序。我希望能够从我自己的自定义组件中访问该主题的详细信息,但我无法弄清楚如何做到这一点。在下面的示例中,this.props.theme 未定义

ReactDOM.render(
    <MuiThemeProvider theme={theme}>
        <App/>
    </MuiThemeProvider>, document.getElementById('root')
);

class App extends Component {
    render() {
        const {classes} = this.props;
        return (
            <div className="App">
                <MainMenu/>
                <div className={classes.root}>
                    <Grid container spacing={8}>
                        <Grid item xs>
                            <Chart theme={this.props.theme}/>
                        </Grid>
                    </Grid>
                </div>
            </div>
        );
    }
}

【问题讨论】:

    标签: reactjs material-ui


    【解决方案1】:

    您需要使用 material-ui 提供的 HOC(高阶组件)(注意我使用的是 beta 版本,YMMV)。

    例子:

    LeftNavigation.jsx

    import React from 'react';
    import PropTypes from 'prop-types';
    import Hidden from 'material-ui/Hidden';
    import Drawer from 'material-ui/Drawer';
    import List from 'material-ui/List';
    import Divider from 'material-ui/Divider';
    
    import { withStyles } from 'material-ui/styles';
    
    import { MailFolderListItems, OtherMailFolderListItems } from '../../../components/tileData';
    
    const styles = theme => ({
      docked: {
        height: '100%',
      },
      drawerPaper: {
        width: 250,
        height: '100%',
        [theme.breakpoints.up('md')]: {
          width: theme.drawerWidth,
          position: 'relative',
          height: '100%',
        },
      },
      drawerHeader: theme.mixins.toolbar,
    });
    
    class LeftNavigation extends React.Component {
      render() {
        const { classes, theme } = this.props;
    
        const drawer = (
          <div>
            <div className={classes.drawerHeader} />
            <Divider />
            <List><MailFolderListItems toggle={this.props.handleDrawerToggle} /></List>
            <Divider />
            <List><OtherMailFolderListItems toggle={this.props.handleDrawerToggle} /></List>
          </div>
        );
    
        return [
          <Hidden mdUp key="mobile">
            <Drawer
              type="temporary"
              anchor={theme.direction === 'rtl' ? 'right' : 'left'}
              open={this.props.mobileOpen}
              classes={{ paper: classes.drawerPaper }}
              onRequestClose={this.props.handleDrawerToggle}
              ModalProps={{ keepMounted: true /* Better open performance on mobile. */ }}
            >
              {drawer}
            </Drawer>
          </Hidden>,
          <Hidden mdDown implementation="css" key="desktop">
            <Drawer
              type="permanent"
              open
              classes={{
                docked: classes.docked,
                paper: classes.drawerPaper,
              }}
            >
              {drawer}
            </Drawer>
          </Hidden>,
        ];
      }
    }
    
    LeftNavigation.propTypes = {
      classes: PropTypes.object.isRequired,
      theme: PropTypes.object.isRequired,
      mobileOpen: PropTypes.bool.isRequired,
      handleDrawerToggle: PropTypes.func.isRequired
    };
    
    export default withStyles(styles, { withTheme: true })(LeftNavigation);
    

    const styles = theme =&gt; ({...}) 是您定义样式的地方。

    export default withStyles(styles, { withTheme: true })(LeftNavigation); 显示了使用高阶组件将样式/主题向下传递给组件的用法。

    我使用withTheme: true,这样不仅可以传递我的样式,还可以传递主题。

    所以对于您的代码,我会执行以下操作:

    import { withStyles } from 'material-ui/styles';
    
    const styles = theme => ({
      root: {
        height: '100%'
      }
    })
    
    class App extends Component {
        render() {
            const {classes} = this.props;
            return (
                <div className="App">
                    <MainMenu/>
                    <div className={classes.root}>
                        <Grid container spacing={8}>
                            <Grid item xs>
                                <Chart theme={this.props.theme}/>
                            </Grid>
                        </Grid>
                    </div>
                </div>
            );
        }
    }
    
    export default withStyles(styles, { withTheme: true})(App); 
    

    【讨论】:

      【解决方案2】:

      你也可以使用 useTheme 钩子!

      import { useTheme } from '@material-ui/styles';
      
      function DeepChild() {
        const theme = useTheme();
        return <span>{`spacing ${theme.spacing}`}</span>;
      }
      

      https://material-ui.com/styles/advanced/#accessing-the-theme-in-a-component

      【讨论】:

      • 请注意,@material-ui/styles 提供了很多很酷的东西,例如默认主题、样式(通常每个人都知道)、主题、使用主题变体、样式化、合并类等等
      【解决方案3】:

      对于使用 Typestipt 和类组件的人,您还需要添加:

      export interface MyComponentNameProps extends WithStyles<typeof styles, true> {
      // your props here...
      theme: Theme
      }
      

      【讨论】:

        猜你喜欢
        • 2021-01-28
        • 2019-11-28
        • 2021-05-23
        • 2020-07-26
        • 2022-01-10
        • 2016-09-29
        • 1970-01-01
        • 2019-03-14
        • 1970-01-01
        相关资源
        最近更新 更多