nCardot
nCardot

Reputation: 6586

Material-UI withStyles props in this.props.classes is undefined

I have two React components in a Create React App app, a parent component (App.js) and a child (QuoteMachine.js). I applied the withStyles HOC API successfully in App.js, but when I used the same format to add one in QuoteMachine.js, passing this.props.classes.card as a property to the Material-UI Card component instance caused a TypeError Cannot read property 'props' of undefined. Is there a problem with having the withStyles HOC in multiple components? Should I use a ThemeProvider instead?

QuoteMachine.js:

import React from 'react';
import Button from '@material-ui/core/Button';
import Typography from '@material-ui/core/Typography';
import Card from '@material-ui/core/Card';
import CardActions from '@material-ui/core/CardActions';
import CardContent from '@material-ui/core/CardContent';
import './QuoteMachine.css';
import { withStyles } from '@material-ui/core/styles';

const styles = {
  card: {
    padding: '30px'
  }
};

// Parentheses around function body is implicit return
const QuoteMachine = (props) => (
  <Card className={this.props.classes.card}>
    <CardContent>
      {props.isDoneFetching ?
        (
          <Typography>
            <p className="quote">{props.randomQuote().quote}</p>
            <p className="author">–{props.randomQuote().author}</p>
          </Typography>
        ) : 'Loading...'}
    </CardContent>

    <CardActions>
      <Button
        size="large"
        onClick={props.nextRandomQuote}
      >
        Next
      </Button>
    </CardActions>
  </Card>
)

export default withStyles(styles)(QuoteMachine);

App.js:

import React, { Component } from 'react';
import QuoteMachine from './QuoteMachine';
import 'typeface-roboto'; // From Material-UI
import { Grid } from '@material-ui/core';
import { withStyles } from '@material-ui/core/styles';
import backgroundImage from './dawn.jpg';

const styles = {
  // container is root component (set in Grid component instance)
  container: {
    display: 'flex',
    alignItems: 'center',
    height: '100vh',
    background: `url(${backgroundImage}) center`,
    backgroundSize: 'cover', // Using this in background causes issues
  }
};

class App extends Component {
  constructor(props) {
    super(props);
    ...
  }

  ....

  render() {
    return (
      <Grid
        id="quote-box"
        className={this.props.classes.container}
        justify="center"
        container
      >
        <Grid xs={11} lg={8} item>
          <QuoteMachine
            isDoneFetching={this.state.isDoneFetching}
            randomQuote={this.randomQuote}
            nextRandomQuote={this.nextRandomQuote}
          />
        </Grid>
      </Grid>
    );
  }
}

export default withStyles(styles)(App);

Upvotes: 0

Views: 2439

Answers (1)

Shubham Khatri
Shubham Khatri

Reputation: 281616

Since QuoteMachine is a functional component, it doesn't have a this instance and the props are available from the argument to the functional component. You would access the classes like

<Card className={props.classes.card}>

Upvotes: 2

Related Questions