CardHeader is not rendering in React - reactjs

I'm playing with React and material-ui, other stuff have worked but for some reason <CardHeader> is not getting rendered.
Below is the code
import React from "react";
import Card from "#material-ui/core/Card";
import CardHeader from "#material-ui/core/Card";
import CardContent from "#material-ui/core/Card";
import CardActions from "#material-ui/core/Card";
import Button from "#material-ui/core/Button";
import Paper from "#material-ui/core/Paper";
import Typography from "material-ui/Typography";
class PaperCard extends React.Component {
render() {
return (
<Card>
<CardHeader title="CaHellord" subheader="Test ME" />
<CardContent>
<Typography type="title">Word of the day</Typography>
<Typography type="headline" component="h2">
impediments
</Typography>
<Typography component="p">adjective</Typography>
</CardContent>
<CardActions>
<Button dense> Learn More </Button>
</CardActions>
</Card>
);
}
}
export default PaperCard;
Could someone point out the obvious which I have missed.

It's just the case of incorrect import.
Replace the import of CardHeader from
import CardHeader from "#material-ui/core/Card";
to
import CardHeader from "#material-ui/core/CardHeader";

Related

CSS Specificity about MUI

I want to build WordPress plugin admin manager screen by MUI, but I find a problem about CSS specificity.
Here it is normal:
enter image description here
But the fact is that:
enter image description here
My code:
import React from 'react';
import ReactDOM from 'react-dom/client';
import Paper from '#mui/material/Paper';
import FormGroup from "#mui/material/FormGroup";
import TextField from '#mui/material/TextField';
import Typography from '#mui/material/Typography';
import Button from "#mui/material/Button";
import Box from "#mui/material/Box";
import StyledEngineProvider from "#mui/material/StyledEngineProvider";
const root = ReactDOM.createRoot(document.getElementById('wpbody'));
root.render(
<Paper sx={{padding: 3}}>
<Typography sx={{padding: 1}}>基础设置</Typography>
<FormGroup sx={{maxWidth: 300}}>
<TextField id="standard-basic" label="App ID" variant={"filled"} sx={{margin: 1}}/>
<TextField id="standard-basic" label="App Secret" variant={"filled"} sx={{margin: 1}}/>
<Box>
<Button variant={"contained"} sx={{margin: 1}}>保存</Button>
</Box>
</FormGroup>
</Paper>
);

Why material-ui components don't display in my App?

So I'm following a react tutorial and in that project material-ui is being used, it's e-commerce, so I have Products.jsx and Product.jsx files.
Product.jsx file:
import React from 'react';
import { Card, CardMedia, CardContent, CardActions, Typography, IconButton} from '#material-ui/core';
import { AddShoppingCart } from '#material-ui/icons';
import MuiThemeProvider from '#material-ui/core/styles/MuiThemeProvider';
const Product = ( {product} ) => {
return (
<MuiThemeProvider>
<Card className="rootie">
<CardMedia className="media" image='' title={product.name} />
<CardContent>
<div className="cardContent">
<Typography variant="h5" gutterBottom>
{product.name}
</Typography>
<Typography variant="h5" gutterBottom>
{product.price}
</Typography>
</div>
<Typography variant="h2" color="textSecondary">{product.description}</Typography>
</CardContent>
<CardActions disableSpacing className="cardActions">
<IconButton aria-label="Add to cart">
<AddShoppingCart/>
</IconButton>
</CardActions>
</Card>
</MuiThemeProvider>
);
}
export default Product;
Products.jsx:
import React from 'react';
import { Grid } from '#material-ui/core';
import Product from '../Product/Product';
import MuiThemeProvider from '#material-ui/core/styles/MuiThemeProvider';
const products = [
{ id: 1, name: 'JBL', description: 'JBL', price: '$100'},
{ id: 2, name: 'AirPods', description: 'AirPods', price: '$100'},
];
const Products = () => {
return (
<MuiThemeProvider>
<Grid container justifyContent="center" spacing={4}>
{products.map((product) =>{
<Grid item key={product.id} xs={12} sm={6} md={4} lg={3}>
<Product product={product}/>
</Grid>
})}
</Grid>
</MuiThemeProvider>
);
}
export default Products;
And my App.js looks like this:
import React from 'react';
import Header from './components/Header/Header';
import Products from './components/Products/Products';
import './App.scss';
const App = () => {
return (
<div>
<Products/>
</div>
)
}
export default App;
So as you see, everything looks okay, but for some reason React doesn't render the components, so the page looks empty. I've searched on the internet and found about 'MuiThemeProvider', but adding it didn't really help either.
You need to create a theme and pass it as prop to ThemeProvider which in turn wraps the entire App during ReactDOM.render stage itself. Something like this:
import * as React from 'react';
import ReactDOM from 'react-dom';
import CssBaseline from '#mui/material/CssBaseline';
import { ThemeProvider } from '#mui/material/styles';
import App from './App';
import theme from './theme';
ReactDOM.render(
<ThemeProvider theme={theme}>
{/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
<CssBaseline />
<App />
</ThemeProvider>,
document.querySelector('#root'),
);
Only then will your Material UI components work as you expect.

How to link external url with button in Material UI?

I'm pretty new to Material-UI and testing my web-app with localhost. Basically, I have created a button that will route to external url (www.google.ca for now) when the user clicks on it. For unknown reason, clicking a button routes to http://localhost:3001/www.google.ca instead of https://www.google.ca. Not sure what the problem is?
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import Card from '#material-ui/core/Card';
import CardActionArea from '#material-ui/core/CardActionArea';
import CardActions from '#material-ui/core/CardActions';
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 Link from '#material-ui/core/Link';
import waterBottle from '../images/tom.jpg';
// All the code has been retrieved from https://material-ui.com/components/cards/#card
const useStyles = makeStyles({
root: {
maxWidth: 345,
},
media: {
height: 140,
},
});
export default function MembersInfo() {
const classes = useStyles();
return (
<Card className={classes.root}>
<CardActionArea>
<CardMedia
className={classes.media}
image={waterBottle}
title="Image"
/>
<CardContent>
<Typography gutterBottom variant="h5" component="h2">
Tom Wong
</Typography>
<Typography variant="body2" color="textSecondary" component="p">
Tom is a business administrative student at xxx university.
</Typography>
</CardContent>
</CardActionArea>
<CardActions>
<Button size="small" color="primary" href="www.google.ca" target="_blank" to = "/url">
Google
</Button>
</CardActions>
</Card>
);
}
In case anyone runs across this issue with using the Link component from Material UI - a few comments addressed some of the issues.
Additionally, make sure you're importing the Link correctly from material ui since they've updated their API. I tried using the API provided ('#mui/material/Link') but had to use their old API (#material-ui/core/Link) for it to work.
If the import is correct, this is the the code that will open up a new tab to google while you're developing using localhost:
<Link target="_blank" href="http://www.google.com" rel="noreferrer">
View Link
</Link>

How to correctly remove padding on Components

I would like to nest a List inside a Card or an Expansion Panel, the problem is that both, the Expansion Panel and List are adding padding to the sides. The result looks really weird...
<Card>
<CardHeader title="Title" subheader="Subheader"/>
<CardContent>
<List>
<ListItem>
<ListItemText
primary={`<--- too much padding`}
/>
</ListItem>
</List>
</CardContent>
</Card>
Here is a running example that shows the issue: https://codesandbox.io/s/material-demo-djzdz
I would like to get rid of the extra padding, I solved the issue temporarily by using the withStyles thingy like this:
import React from "react";
import Card from "#material-ui/core/Card";
import CardHeader from "#material-ui/core/CardHeader";
import List from "#material-ui/core/List";
import ListItem from "#material-ui/core/ListItem";
import ListItemText from "#material-ui/core/ListItemText";
import { withStyles } from "#material-ui/core/styles";
import MuiCardContent from "#material-ui/core/CardContent";
const NestedCardContent = withStyles(theme => ({
root: {
padding: 0
}
}))(MuiCardContent);
export default function Color() {
return (
<Card>
<CardHeader title="Title" subheader="Subheader" />
<NestedCardContent>
<List>
<ListItem>
<ListItemText primary={`padding is fine`} />
</ListItem>
</List>
</NestedCardContent>
</Card>
);
}
Run it in codesandbox: https://codesandbox.io/s/material-demo-kyx38
As you can see, it works. But it feels absolutely hackish...
I previously tried that mx, px spacing thing described here: https://material-ui.com/customization/spacing/
Without success either - changed nothing.
Furthermore I need this Kind of NestedCardContent in more than one Component. So how would you do it in a clean way? What is considered as a good practice here?
I recommend just removing the CardContent tag entirely. If you look at the source for CardContent, the only thing it does is padding.
If you don't want that padding just do:
import React from "react";
import Card from "#material-ui/core/Card";
import CardHeader from "#material-ui/core/CardHeader";
import List from "#material-ui/core/List";
import ListItem from "#material-ui/core/ListItem";
import ListItemText from "#material-ui/core/ListItemText";
export default function Color() {
return (
<Card>
<CardHeader title="Title" subheader="Subheader" />
<List>
<ListItem>
<ListItemText primary={`padding is fine`} />
</ListItem>
</List>
</Card>
);
}
This solution removes the 24px bottom padding as well which may or may not be what you want. If you want to retain the extra bottom padding, then just move your NestedCardContent component into its own file so you can import/reuse it.

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);
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}>

Resources