简体   繁体   中英

Use Material-UI HOC in Class Component

I'm trying to use material UI in my class component, instead of converting everything to Hooks. I'm not sure which method is easier, Hooks or retro-fitting what I have.

https://material-ui.com/styles/basics/#higher-order-component-api

Here's my code:

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      hits: [],
      desc: [],
    };
  }

  componentDidMount() {
    this.fetchData();
  }

  fetchData() {
    fetch(
      `https://api.openweathermap.org/data/2.5/onecall?lat=30.2672&lon=-97.7431&units=imperial&exclude=minutely&appid=${process.env.REACT_APP_WEATHER_KEY}`
    )
      .then((json) => json.json())
      .then((data) => {
        this.setState({
          hits: data.current,
          desc: data.current.weather[0],
        });
        console.log(data);
      })

      .catch((error) => console.log("parsing failed", error));
  }

  render() {
    const useStyles = makeStyles({
      root: {
        maxWidth: 450,
        margin: "0 auto",
      },
      MuiCardContent: {
        padding: 0,
        "&:last-child": {
          paddingBottom: 2,
        },
      },
      title: {
        fontSize: 14,
      },
    });

    const unixTimestamp = this.state.hits.sunset * 1000;
    const date = new Date(unixTimestamp);

    const localized = date.toLocaleString();

    const classes = useStyles();
    return (
      <Card className={classes.root} variant="outlined">
        <CardContent className={classes.MuiCardContent}>
          <Typography
            className={classes.title}
            color="textSecondary"
            gutterBottom
          >
            Current Weather
          </Typography>
          <Typography variant="subtitle1" component="h2">
            <div>{this.state.desc.main}</div>
            <div>Temp: {this.state.hits.temp} F</div>
            <div>Feels Like: {this.state.hits.feels_like} F</div>
            <div>Humidity: {this.state.hits.humidity}%</div>
            <div>Sunset: {localized}</div>
            <div>UV Index: {this.state.hits.uvi} (Take caution when above 8)</div>
 </Typography>
        </CardContent>
      </Card>
    );
  }
}

export default App;

I looked at the material-ui docs, but I'm confused on how to implement this inside of a class component. I'm new to hooks so that seems a bit crazy right now.

In your case, if you want to style your class component, you should use withStyles.

Try this:

 import React, { Component } from 'react'; import { withStyles } from '@material-ui/core/styles'; const useStyles = (theme) => ({ root: { paddingTop: theme.spacing(8), backgroundColor: "white" }, }) class App extends Component { render() { const { classes } = this.props return( <div className = {classes.root}>... </div> ); } } export default withStyles(useStyles)(App);

makeStyles returns a hook that is only valid with functional components. You've correctly found the withStyles HOC, but you just need to use it. Factor out and externally define your style object, and pass to the withStyles() HOC.

...
import { withStyles } from '@material-ui/core/styles'; // <-- import withStyles HOC
...

const styles = {
  root: {
    maxWidth: 450,
    margin: "0 auto",
  },
  MuiCardContent: {
    padding: 0,
    "&:last-child": {
      paddingBottom: 2,
    },
  },
  title: {
    fontSize: 14,
  },
}

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      hits: [],
      desc: [],
    };
  }

  componentDidMount() {
    this.fetchData();
  }

  fetchData() {
    fetch(
      `https://api.openweathermap.org/data/2.5/onecall?lat=30.2672&lon=-97.7431&units=imperial&exclude=minutely&appid=${process.env.REACT_APP_WEATHER_KEY}`
    )
      .then((json) => json.json())
      .then((data) => {
        this.setState({
          hits: data.current,
          desc: data.current.weather[0],
        });
        console.log(data);
      })

      .catch((error) => console.log("parsing failed", error));
  }

  render() {
    const unixTimestamp = this.state.hits.sunset * 1000;
    const date = new Date(unixTimestamp);
    const localized = date.toLocaleString();

    const { classes } = this.props; // <-- destructure injected classes prop

    return (
      <Card className={classes.root} variant="outlined">
        <CardContent className={classes.MuiCardContent}>
          <Typography
            className={classes.title}
            color="textSecondary"
            gutterBottom
          >
            Current Weather
          </Typography>
          <Typography variant="subtitle1" component="h2">
            <div>{this.state.desc.main}</div>
            <div>Temp: {this.state.hits.temp} F</div>
            <div>Feels Like: {this.state.hits.feels_like} F</div>
            <div>Humidity: {this.state.hits.humidity}%</div>
            <div>Sunset: {localized}</div>
            <div>UV Index: {this.state.hits.uvi} (Take caution when above 8)</div>
 </Typography>
        </CardContent>
      </Card>
    );
  }
}

export default withStyles(styles)(App); // <-- decorate App with classes prop

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM