What is wrong with my iconButton in React JS? - reactjs

The console announce mistake at my IconButton open tag as unexpected token. i have installed material ui...i don't know what is the problem? can anyone help me? Thank you so much!
This is my product.js:
import React from 'react'
import {
Card,
CardMedia,
CardContent,
CardActions,
Typography,
IconButton
} from '#material-ui/core'
import {
AddShoppingCart
} from '#material-ui/icons'
import useStyles from './styles'
const Product = ({
product
}) => {
const classes = useStyles()
return (
<Card className={classes.root}>
<CardMedia className={classes.media} image='' title={product.name} />
<CardContent>
<div className={classes.cardContent}>
<Typography gutterBottom variant="h5" >
{product.name}
</Typography>
<Typography variant="h5" >
{product.price}
</Typography>
</div>
</CardContent>
<CardActions disableSpacing className={classes.cardActions}>
<IconButton aria-label="Add to Cart">
<AddShoppingCart />
</IconButton>
</CardActions>
</Card>
)
}
export default Product
This is my styles.js:
import {
makeStyles
} from '#material-ui/core/styles'
export default makeStyles(() => ({
{
root: {
maxWidth: '100%'
},
media: {
height: 0,
paddingTop: '56.25%'
},
cardActions: {
display: 'flex',
justifyContent: 'space-between'
},
}
}))
Btw i don't get where useStyles in my product.js come from when in my styles.js it's makeStyles not useStyles (i follow a tutorial on yt and he does so)

This: import useStyles from './styles' is named that because you/him wanted to, because you're exporting export default makeStyles.
export default means that you can import it with any name you want, its not a named export.
The problem maybe because here:
// You're returning an object of an object, instead of the inner { root: ... }.
({
{
root: {
maxWidth: '100%'
},
media: {
height: 0,
paddingTop: '56.25%'
},
cardActions: {
display: 'flex',
justifyContent: 'space-between'
},
}
}))
so maybe classes is not defined correctly, it would be needed the error stack to make sure where the error is, or at least a simple jsfiddle with the error would do.

There is nothing wrong with your IconButton component.
Some hints:
You can import your styles as classes right away, otherwise I doubt the class definitions will work at all.
Ensure you have installed #material-ui/icons
I took your code and did above changes:
import React from "react";
import {
Card,
CardMedia,
CardContent,
CardActions,
Typography,
IconButton
} from "#material-ui/core";
import { AddShoppingCart } from "#material-ui/icons";
import classes from "./styles";
const Product = ({ product }) => {
return (
<Card className={classes.root}>
<CardMedia className={classes.media} image="/" title={product.name} />
<CardContent>
<div className={classes.cardContent}>
<Typography gutterBottom variant="h5" component="h2">
{product.name}
</Typography>
<Typography gutterBottom variant="h5" component="h2">
{product.price}
</Typography>
</div>
</CardContent>
<CardActions disableSpacing className={classes.cardActions}>
<IconButton aria-label="Add to Cart">
<AddShoppingCart />
</IconButton>
</CardActions>
</Card>
);
};
export default Product;
See: https://codesandbox.io/s/ecstatic-sea-m9k33?file=/src/Product.js

we have used an arrow function to inline the event handler for out input field
So use
function Product({product}) {...}
instead of
const Product = ({ product }) => {}

Related

How to enlarge a carousel MUI card on hover

I'm creating a Carousel similar to Netflix's, where if you hover over a card, it will enlarge it and show more details.
My problem is that, instead of enlarging just the hovered card, it's enlarging all the other cards.
Here's the component:
import * as React from 'react';
import {useState} from 'react';
import Card from '#mui/material/Card';
import CardHeader from '#mui/material/CardHeader';
import CardMedia from '#mui/material/CardMedia';
import CardContent from '#mui/material/CardContent';
import CardActions from '#mui/material/CardActions';
import Avatar from '#mui/material/Avatar';
import IconButton from '#mui/material/IconButton';
import Typography from '#mui/material/Typography';
import {red} from '#mui/material/colors';
import FavoriteIcon from '#mui/icons-material/Favorite';
import ShareIcon from '#mui/icons-material/Share';
import {makeStyles} from '#mui/styles';
const ctCardHoveredSx = {
maxWidth: 345,
"&:hover": {},
"& .ct-card": {
display: "none"
},
"&:hover .ct-card": {
display: "flex"
},
"& .ct-card-panel": {
transition: "transform 0.15s ease-in-out"
},
"&:hover .ct-card-panel": {
transform: "scale3d(1.05, 1.05, 1)"
}
}
const useStyles = makeStyles({
root: {
maxWidth: 310,
transition: "transform 0.15s ease-in-out",
"& .ct-card": {
display: "none"
}
},
cardHovered: {
transform: "scale3d(1.05, 1.05, 1)",
"&:hover .ct-card": {
display: "flex"
}
}
});
const CtCard = () => {
const classes = useStyles();
const [hovered, setHovered] = useState<boolean>(false);
return (
<Card className={classes.root}
classes={{root: hovered ? classes.cardHovered : ""}}
onMouseOver={() => setHovered(true)}
onMouseOut={() => setHovered(false)}
>
<CardMedia
component="img"
height="194"
image="https://picsum.photos/200/300"
alt="Paella dish"
/>
<CardHeader
avatar={
<Avatar sx={{bgcolor: red[500]}} aria-label="recipe">
R
</Avatar>
}
title="Lorem Ipsum"
subheader="Lorem Ipsum"
/>
<CardContent className={'ct-card'}>
<Typography variant="body2" color="text.secondary">
This impressive paella is a perfect party dish and a fun meal to cook
together with your guests. Add 1 cup of frozen peas along with the mussels,
if you like.
</Typography>
</CardContent>
<CardActions disableSpacing className={'ct-card'}>
<IconButton aria-label="add to favorites">
<FavoriteIcon/>
</IconButton>
<IconButton aria-label="share">
<ShareIcon/>
</IconButton>
</CardActions>
</Card>
);
}
export default CtCard;
And how it's used:
<Stack
position={'relative'}
direction={'row'}
spacing={1}
>
{
Array(pageCount).fill(null).map((v, i) =>
<CtCard/>
)
}
</Stack>
Perhaps start by try giving each <CtCard/> being mapped a unique key:
{
Array(pageCount)
.fill(null)
.map((v, i) => <CtCard key={i} />);
}
The index is not a good option for key either, but use just for testing purposes and switch to some actual unique ID later.
Based on your description the events setting state do fire as expected, so it would seem that it might be the updating of the components causing the issue.

Material-UI v5: makeStyles's not being imported

When I am trying to import "makeStyles" using :
import { makeStyles } from '#mui/styles';
it's not working. The page becomes blank when I run.
But It's working when I change the code and use V4:
import { makeStyles } from "#material-ui/core/styles";
I've installed alll the dependencies that is required. Why It's not working using V5 of material-ui?
Here is my code (styles.js):
import { makeStyles } from "#mui/material";
export default makeStyles((theme) => ({
title: {
display: "none",
[theme.breakpoints.up("sm")]: {
display: "block",
},
},
}));
Header.jsx:
import React from "react";
import { AppBar, Toolbar, Typography, InputBase, Box } from "#mui/material";
import SearchIcon from "#mui/icons-material/Search";
import useStyles from "./styles";
const Header = () => {
const classes = useStyles();
return (
<AppBar position="static">
<Toolbar>
<Typography variant="h5" className={classes.title}>
Travel Advsior
</Typography>
<Box display="flex">
<Typography variant="h6" className={classes.title}>
Explore new places
</Typography>
<div>
<div>
<SearchIcon />
</div>
<InputBase placeholder="Search..." />
</div>
</Box>
</Toolbar>
</AppBar>
);
};
export default Header;

MUI makeStyles isn't working on the Card component

I have this component called Product which is based off this example. Here is my component:
Product.tsx:
import useStyles from './useStyles'
const Product: React.FC = () => {
const classes = useStyles();
return (
<Card className={classes.secondaryBorder}>
<CardActionArea>
<CardContent>
<Typography gutterBottom variant="h5">
This is my title
</Typography>
<Typography variant="body2" color="text.secondary">
This is my body
</Typography>
</CardContent>
</CardActionArea>
</Card>
);
};
useStyles.ts:
import { makeStyles } from '#mui/styles';
const useStyles = makeStyles({
secondaryBorder: {
border: '2px solid blue',
},
flex: {
display: 'flex',
},
});
The problem is that the Card component does not have the secondaryBorder i.e. it does not have a blue border around it. So what is the problem?
Thank you!

TypeError: Cannot read properties of undefined (reading 'up') MUI

In my Header component my custom styling are coming from style.js where I've used makeStyles from #mui/styles. But In there while setting up the [theme.breakpoints.up("sm")] I'm getting the error above. I tried wrapping the index.js with themeProvider and passed createTheme as prop. but it is giving me another error. I tried looking up the docs but couldn't figure it out.
styles.js
import { makeStyles } from "#mui/styles";
import { alpha } from "#mui/material/styles";
export default makeStyles((theme) => ({
title: {
display: "none",
[theme.breakpoints.up("sm")]: {
display: "block",
},
},
...
})
)
Header component
import React from "react";
import useStyles from "./styles";
import { AppBar, Toolbar, Typography, InputBase, Box } from "#mui/material";
import { Autocomplete } from "#react-google-maps/api";
import { SearchIcon } from "#mui/icons-material/Search";
const Header = () => {
const classes = useStyles();
return (
<AppBar position="static">
<Toolbar className={classes.toolbar}>
<Typography variant="h5" className={classes.title}>
Travel Companion
</Typography>
<Box display="flex">
<Typography variant="h6" className={classes.title}>
Explore new places
</Typography>
<Autocomplete>
<div className={classes.search}>
<div className={classes.searchIcon}>
<SearchIcon />
</div>
<InputBase
classes={{ root: classes.inputRoot, input: classes.inputInput }}
placeholder="Search"
/>
</div>
</Autocomplete>
</Box>
</Toolbar>
</AppBar>
);
};
export default Header;

How can I reuse code wrapping Material-UI's Grid while varying the number of columns?

I would like the second grid block under the title "Other Projects of Note" to be mapped through as a 3 column grid. How can I do this without creating a new component? Material-UI controls it's columns with the grid item xs={12} sm={6} and on the 3 column grid I'd need it to read as grid item xs={12} sm={6} lg={4}.
It seems like I'd be copying and pasting the <Card /> component and renaming it to achieve this. I'd like to avoid that. Demo below:
codesandbox
Here's the code for my current Card component:
import React from 'react';
import Grid from '#material-ui/core/Grid';
import Card from '#material-ui/core/Card';
import CardActionArea from '#material-ui/core/CardActionArea';
import CardActions from '#material-ui/core/CardActions';
import { makeStyles } from '#material-ui/core/styles';
import { loadCSS } from 'fg-loadcss';
import CardContent from '#material-ui/core/CardContent';
import CardMedia from '#material-ui/core/CardMedia';
import Button from '#material-ui/core/Button';
import Typography from '#material-ui/core/Typography';
import Box from '#material-ui/core/Box';
import Icon from '#material-ui/core/Icon';
import GitHubIcon from '#material-ui/icons/GitHub';
import Tooltip from '#material-ui/core/Tooltip';
import Zoom from '#material-ui/core/Zoom';
import Link from '#material-ui/core/Link';
const useStyles = makeStyles((theme) => ({
root: {
maxWidth: '100%',
flexGrow: 1,
},
cardGrid: {
paddingTop: theme.spacing(2),
},
media: {
height: 340,
},
button: {
margin: theme.spacing(1),
},
arrow: {
color: theme.palette.common.black,
},
tooltip: {
backgroundColor: theme.palette.common.black,
},
icons: {
'& > .fab': {
marginRight: theme.spacing(4),
},
margin: '1rem 0',
},
}));
function TwoCard(props) {
const classes = useStyles();
React.useEffect(() => {
const node = loadCSS(
'https://use.fontawesome.com/releases/v5.12.0/css/all.css',
document.querySelector('#font-awesome-css')
);
return () => {
node.parentNode.removeChild(node);
};
}, []);
return (
<>
<Grid item xs={12} sm={6}>
<Card>
<CardActionArea>
<CardMedia
className={classes.media}
image={props.card.image}
title='Contemplative Reptile'
/>
<CardContent className={classes.content}>
<Typography gutterBottom variant='h5' component='h2'>
{props.card.project}
</Typography>
<Typography variant='subtitle1' gutterBottom>
{props.card.framework}
</Typography>
<Typography gutterBottom variant='body2' component='p'>
{props.card.description}
</Typography>
<Box className={classes.icons}>
<Typography gutterBottom variant='subtitle2'>
TOOLS USED
</Typography>
<Tooltip
TransitionComponent={Zoom}
arrow
title='REACT'
aria-label='react'
>
<Icon className='fab fa-react fa-3x' color='primary' />
</Tooltip>
<Tooltip
TransitionComponent={Zoom}
arrow
title='HTML5'
aria-label='add'
>
<Icon className='fab fa-html5 fa-3x' color='primary' />
</Tooltip>
<Tooltip
TransitionComponent={Zoom}
arrow
title='CSS3'
aria-label='add'
>
<Icon className='fab fa-css3 fa-3x' color='primary' />
</Tooltip>
</Box>
</CardContent>
</CardActionArea>
<CardActions>
<Button variant='outlined' size='small' color='primary'>
<Link
href={props.card.projectUrl}
target='_blank'
rel='noopener noreferrer'
className={classes.links}
underline='none'
color='inherit'
>
View Project
</Link>
</Button>
<Button
variant='outlined'
size='small'
color='primary'
className={classes.button}
endIcon={<GitHubIcon />}
>
<Link
href={props.card.githubUrl}
target='_blank'
rel='noopener noreferrer'
underline='none'
color='inherit'
>
Code
</Link>
</Button>
</CardActions>
</Card>
</Grid>
</>
);
}
export default TwoCard;
and here's the code that uses that Card component:
import React from "react";
import Grid from "#material-ui/core/Grid";
import Card from "./Card.js";
import { Typography } from "#material-ui/core";
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles((theme) => ({
headings: {
padding: "20px 0"
}
}));
function Projects(props) {
const classes = useStyles();
let cards = props.data.map((card, i) => {
return <Card card={card} key={i} />;
});
return (
<>
<Typography variant="h4" gutterBottom>
Featured Projects
</Typography>
<Grid container spacing={2}>
{cards}
</Grid>
<Typography variant="h4" className={classes.headings}>
Other Projects of note
</Typography>
<Grid container spacing={2}>
{cards}
</Grid>
</>
);
}
export default Projects;
You can pass a prop to your Card component to control whether it is two-column or three-column. For instance, you can pass a maxColumns prop and use it in the following manner:
<Grid item xs={12} sm={6} lg={maxColumns > 2 ? 4 : undefined}>
Then your Projects component can pass the prop (in my example, I'm defaulting maxColumns to 2, so it doesn't need to be specified in that case):
import React from "react";
import Grid from "#material-ui/core/Grid";
import Card from "./Card.js";
import { Typography } from "#material-ui/core";
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles((theme) => ({
headings: {
padding: "20px 0"
}
}));
function Projects(props) {
const classes = useStyles();
let twoColumnCards = props.data.map((card, i) => {
return <Card card={card} key={i} />;
});
let threeColumnCards = props.data.map((card, i) => {
return <Card maxColumns={3} card={card} key={i} />;
});
return (
<>
<Typography variant="h4" gutterBottom>
Featured Projects
</Typography>
<Grid container spacing={2}>
{twoColumnCards}
</Grid>
<Typography variant="h4" className={classes.headings}>
Other Projects of note
</Typography>
<Grid container spacing={2}>
{threeColumnCards}
</Grid>
</>
);
}
export default Projects;

Resources