0

I have a separate App.css file that has global css attributes and have classes for responsiveness. The issue is I want to render elements differently for separate devices but can't seem to figure out how to do that as using conditionals isn't applying as such.

import UserItem from "./UserItem";
import Spinner from "../layout/Spinner";
import PropTypes from "prop-types";

const Users = ({ users, loading }) => {
  if (loading) {
    return <Spinner />;
  } else {
    return (
      <div style={userStyle} className='body'>
        {users.map((user) => {
          return <UserItem key={user.id} user={user} />;
        })}
      </div>
    );
  }
};

const windowWidth = window.innerWidth;

Users.propTypes = {
  users: PropTypes.array.isRequired,
  loading: PropTypes.bool.isRequired,
};

const userStyle = {
  display: "grid",
  gridTemplateColumns: "repeat(3, 1fr)",
  gridGap: "1rem",
};

export default Users;

My css @media query which I am trying to apply to effect change on a small device.

/* Mobile Styles */
@media (max-width: 700px) {
  .hide-sm {
    display: none;
  }
}

How do I implement this @media css style so that it can render the page differents through jsx?

2 Answers2

0

You can use material ui. that will fulfil your requirement. Please check this example:

import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
import { green } from '@material-ui/core/colors';

const useStyles = makeStyles(theme => ({
  root: {
    padding: theme.spacing(1),
    [theme.breakpoints.down('sm')]: {
      backgroundColor: theme.palette.secondary.main,
    },
    [theme.breakpoints.up('md')]: {
      backgroundColor: theme.palette.primary.main,
    },
    [theme.breakpoints.up('lg')]: {
      backgroundColor: green[500],
    },
  },
}));

export default function MediaQuery() {
  const classes = useStyles();
  return (
    <div className={classes.root}>
      <Typography variant="subtitle1">{'down(sm): red'}</Typography>
      <Typography variant="subtitle1">{'up(md): blue'}</Typography>
      <Typography variant="subtitle1">{'up(lg): green'}</Typography>
    </div>
  );
}

Material UI

You can use following example too.

class Card extends Component {

  constructor() {

    super();

    this.mediaQuery = {
      desktop: 1200,
      tablet: 768,
      phone: 576,
    };

    this.state = {
      windowWidth: null
    };
  }

  componentDidMount() {
    window.addEventListener('resize', () => {
      this.setState({windowWidth: document.body.clientWidth})
    });
  }

  render() {
    return (
      <div style={{
        width: this.state.windowWidth > this.mediaQuery.phone
          ? '50%'
          : '100%',
        //more styling :)
      }}>
        <!-- <Card> contents -->
      </div>
    );
  }
}

Source

Khabir
  • 5,370
  • 1
  • 21
  • 33
  • I wanted to use the vanilla cs media classes that I already have. Can't that work? – Mufasatoday May 08 '20 at 22:39
  • @Mufasatoday, I have added another example. Please check whether it works for you or not. – Khabir May 08 '20 at 22:50
  • Still not the response I wanted. I have a separate files with css media query class attached here - and I want to use those classes to render my page differently for different devices but only using my classes that I had defined. – Mufasatoday May 08 '20 at 23:16
  • @Mufasatoday is it helpful for you? https://medium.com/@ttennant/react-inline-styles-and-media-queries-using-a-custom-react-hook-e76fa9ec89f6 – Khabir May 08 '20 at 23:39
0

I suggest that use CSS @media query to make responsive layouts. But if you insist on implement with JS and React you should get windowWidth after component mounted. You can use useEffect hook to do so and save value in a state:

const [windowWidth, setWindowWidth] = useState('');
useEffect(() => {
    setWindowWidth(window.innerWidth) // or better one -> window.clientWidth
});
IVIosi
  • 497
  • 4
  • 10
  • Thank you for this I am using CSS @media query already but I am applying them and they are not effecting any change. How do I do that? – Mufasatoday May 08 '20 at 23:17
  • @Mufasatoday I saw your edits. You could use classnames to add different styles under media queries. In your edit you define ".body" class but that one is not used in your components. Did you mean "body" HTML element? if so then you should use it without dot (.) – IVIosi May 08 '20 at 23:43
  • It shouldn't be ".body" I just changed it to see if it could apply any changes. I have been using className='hide-sm' which displays: none on small devices but it is not showing any changes. I have been applying it on the div that has style={userStyle} – Mufasatoday May 08 '20 at 23:54
  • @Mufasatoday Maybe you are not using media query in right way. Check [this question's](https://stackoverflow.com/questions/7859336/why-are-my-css3-media-queries-not-working) answers. – IVIosi May 09 '20 at 00:53
  • I did find an a way of solving it. I used conditionals to render it using media query as a tag over it and it worked. Thanks alot. – Mufasatoday May 14 '20 at 06:44
  • @Mufasatoday You're so welcome. If you don't mind please rate my answer up and accept this answer using check mark icon. – IVIosi May 14 '20 at 08:42