How to use theme in styles for custom functional components - reactjs

When I try compiling the app it displays a certain error "TypeError:undefined has no properties" though I want to render styled components into the grid tags though in function based component method
const styles = theme => ({
root: {
height: '100vh',
},
image: {
},
paper: {
margin: theme.spacing(8, 4),
},
avatar: {
margin: theme.spacing(1),
backgroundColor: theme.palette.secondary.main,
},
form: {
width: '100%',
marginTop: theme.spacing(1),
},
submit: {
margin: theme.spacing(3, 0, 2),
},
});
const SignIn = (props) => {
const classes = this.props;
return(
<Grid container component="main" className={classes.root}>
<CssBaseline />
<Grid item xs={false} sm={4} md={7} className={classes.image} />
<Grid item xs={12} sm={8} md={5} component={Paper} elevation={6} square>
<div className={classes.paper}>
<Typography component="h1" variant="h5">
Welcome to web
</Typography>
<Avatar className={classes.avatar}>
<LockOutlinedIcon />
</Avatar>
<form className={classes.form} noValidate>
//content
</form>
</div>
</Grid>
</Grid>
);
}
export default withStyles(styles)(SignIn);

Access or destructure classes from props, not this.props.
const { classes } = props;
You can also destructure props right in the function definition.
const SignIn = ({ classes }) => {...

Related

Use Refs In Material UI

I'm trying to use Refs in Material UI to change Image src but it gives me an 'Undefined' error. It looks like the link is getting created but not being applied as the Images src, I feel like the problem lies in line 10 .
CodeSandBox - https://codesandbox.io/s/complexgrid-material-demo-forked-h6zfqh?file=/demo.tsx
const [loading] = useState(true);
const imageRef = React.useRef();
let txt = "IGO";
useEffect(() => {
imageRef.current.src = `https://flightaware.com/images/airline_logos/90p/${txt}.png`;
console.log(imageRef.current.src);
},
[loading, imageRef]);
<ButtonBase sx={{ width: 128, height: 128 }}>
<Img alt="complex" ref={imageRef} />
</ButtonBase>
You can use a list of references an change the image like you was doing.
I let you a functional code that it works like I think you want :)
import * as React from "react";
import { styled } from "#mui/material/styles";
import Grid from "#mui/material/Grid";
import D34, { useEffect, useState } from "react";
import Paper from "#mui/material/Paper";
import Typography from "#mui/material/Typography";
import ButtonBase from "#mui/material/ButtonBase";
import Data from "./abc.json";
const Img = styled("img")({
margin: "auto",
display: "block",
maxWidth: "100%",
maxHeight: "100%"
});
export default function ComplexGrid() {
const [loading] = useState(true);
const imagesRef = [];
let txt = "IGO";
useEffect(() => {
imagesRef.forEach((refImg) => {
refImg.src = `https://flightaware.com/images/airline_logos/90p/${txt}.png`;
});
/*imageRef.current.src = `https://flightaware.com/images/airline_logos/90p/${txt}.png`;
console.log(imageRef.current.src);*/
}, [loading]);
return (
<div className="hello">
{Data.response.map((post, posPost) => {
return (
<Paper
sx={{
pt: 1,
border: 1,
boxShadow: 0,
mt: 1,
maxWidth: 900,
flexGrow: 1,
backgroundColor: (theme) =>
theme.palette.mode === "dark" ? "#1A2027" : "#fff"
}}
>
<Grid container spacing={2}>
<Grid item>
<ButtonBase sx={{ width: 128, height: 128 }}>
<Img alt="complex" ref={(imageRef) => {
if (!imagesRef[posPost]) {
imagesRef.push(imageRef);
}
}} />
</ButtonBase>
</Grid>
<Grid item xs={12} sm container>
<Grid item xs container direction="column" spacing={2}>
<Grid item xs>
<Typography
gutterBottom
variant="subtitle1"
component="div"
>
Standard license
</Typography>
<Typography variant="body2" gutterBottom>
Full resolution 1920x1080 • JPEG
</Typography>
<Typography variant="body2" color="text.secondary">
ID: 1030114
</Typography>
</Grid>
<Grid item></Grid>
</Grid>
<Grid item>
<Typography
variant="subtitle1"
component="div"
sx={{ px: 2, p: 2 }}
>
$19.00
</Typography>
</Grid>
</Grid>
</Grid>
</Paper>
);
})}
</div>
);
}
you can use useState to change the src
const [img, setImg] = useState()
let txt = "IGO";
useEffect(() => {
setImg(`https://flightaware.com/images/airline_logos/90p/${txt}.png`)
}, [loading]);
{img && <Img alt="complex" src={img} />}
The main problem is the way to use ref.
At the moment, you are using same ref for same image component.
In order to manage the image tags well, you should use different ref for each image tab.
Please refer this code.
import * as React from "react";
import { styled } from "#mui/material/styles";
import Grid from "#mui/material/Grid";
import D34, { useEffect, useState } from "react";
import Paper from "#mui/material/Paper";
import RootRef from "#material-ui/core/RootRef";
import Typography from "#mui/material/Typography";
import ButtonBase from "#mui/material/ButtonBase";
import Data from "./abc.json";
import { red } from "#mui/material/colors";
const Img = styled("img")({
margin: "auto",
display: "block",
maxWidth: "100%",
maxHeight: "100%"
});
export default function ComplexGrid() {
const [loading] = useState(true);
const imageRef = React.useRef();
let txt = "IGO";
useEffect(() => {
console.log(imageRef.current.src);
if (imageRef.current.src === "")
imageRef.current.src = `https://flightaware.com/images/airline_logos/90p/${txt}.png`;
}, [loading, imageRef]);
return (
<div className="hello">
<Img alt="complex" ref={imageRef} />
{Data.response.map((post) => {
return (
<Paper
sx={{
pt: 1,
border: 1,
boxShadow: 0,
mt: 1,
maxWidth: 900,
flexGrow: 1,
backgroundColor: (theme) =>
theme.palette.mode === "dark" ? "#1A2027" : "#fff"
}}
>
<Grid container spacing={2}>
<Grid item>
<ButtonBase sx={{ width: 128, height: 128 }}>
{/* <Img alt="complex" ref={imageRef} /> */}
</ButtonBase>
</Grid>
<Grid item xs={12} sm container>
<Grid item xs container direction="column" spacing={2}>
<Grid item xs>
<Typography
gutterBottom
variant="subtitle1"
component="div"
>
Standard license
</Typography>
<Typography variant="body2" gutterBottom>
Full resolution 1920x1080 • JPEG
</Typography>
<Typography variant="body2" color="text.secondary">
ID: 1030114
</Typography>
</Grid>
<Grid item></Grid>
</Grid>
<Grid item>
<Typography
variant="subtitle1"
component="div"
sx={{ px: 2, p: 2 }}
>
$19.00
</Typography>
</Grid>
</Grid>
</Grid>
</Paper>
);
})}
</div>
);
}
Hope it would be helpful for you.
Thanks

Putting gradient background using makeStyles

For some reason, it doesn't respect background: 'linear-gradient(to right, blue.200, blue.700)' under makeStyles. Why is that? All I need to do is put a gradient background on the entire space. <Container className={classes.root}> should probably be a div, what do you think?
import { useState, useEffect } from 'react';
import type { NextPage } from 'next';
import Container from '#mui/material/Container';
import Box from '#mui/material/Box';
import { DataGrid, GridColDef } from '#mui/x-data-grid';
import { createStyles, Grid, Paper, Theme, Typography } from '#mui/material';
import { makeStyles } from '#mui/styles';
import Skeleton from '#mui/material/Skeleton';
import FormOne from './../src/FormOne';
const LoadingSkeleton = () => (
<Box
sx={{
height: 'max-content',
}}
>
{[...Array(10)].map((_, index) => (
<Skeleton variant="rectangular" sx={{ my: 4, mx: 1 }} key={index} />
))}
</Box>
);
const columns: GridColDef[] = [
{ field: 'id', headerName: 'ID' },
{ field: 'title', headerName: 'Title', width: 300 },
{ field: 'body', headerName: 'Body', width: 600 },
];
const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
height: '100vh',
overflow: 'auto',
background: `linear-gradient(to right, blue.200, blue.700)`,
},
})
);
const Home: NextPage = () => {
const classes = useStyles();
const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(true);
// fetch data from fake API
useEffect(() => {
setInterval(
() =>
fetch('https://jsonplaceholder.typicode.com/posts')
.then((response) => response.json())
.then((data) => {
setPosts(data);
setLoading(false);
}),
3000
);
}, []);
return (
<Container
maxWidth={false}
// sx={{
// height: '100vh',
// overflow: 'auto',
// background: `linear-gradient(to right, ${blue[200]}, ${blue[700]})`,
// }}
className={classes.root}
>
<Container component="main" maxWidth="lg" sx={{ mt: 3, mb: 3 }}>
<Grid container spacing={{ xs: 2, md: 3 }}>
<Grid item xs={6}>
<Paper sx={{ padding: 3 }}>
<Typography component="h1" variant="h4" align="center">
GUI #1
</Typography>
<FormOne />
</Paper>
</Grid>
<Grid item xs={6}>
<Paper sx={{ padding: 3 }}>
<Typography component="h1" variant="h4" align="center">
GUI #2
</Typography>
<FormOne />
</Paper>
</Grid>
<Grid item xs={12}>
<Paper sx={{ padding: 3 }}>
<DataGrid
sx={{ height: '650px' }} // either autoHeight or this
rows={posts}
columns={columns}
pageSize={10}
// autoHeight
rowsPerPageOptions={[10]}
disableSelectionOnClick
disableColumnMenu
disableColumnSelector
components={{
LoadingOverlay: LoadingSkeleton,
}}
loading={loading}
/>
</Paper>
</Grid>
</Grid>
</Container>
</Container>
);
};
export default Home;
I think its because you pass it as a string and it simply doesnt recognice what blue.200 is etc.
try:
background: `linear-gradient(to right, ${blue[200]}, ${blue[700])}`,
#Edit
You actualy need to import color that you want to use from #mui/color
import { blue } from "#mui/material/colors";
and then use it as I mentioned before
here is codesandbox preview and here is codesandbox code
hope this is what we want to achieve
Instead of using background use backgroundImage. This should fix the problem.
The code should be
backgroundImage: `linear-gradient(to right, blue[200], blue[700])`,

How to implement and read the values from socket IO and update the React application with the values?

I am new to socket io and I could find only chat app examples.
Here I have an application example NAT component, whenever we visit this page, I want the NAT page to prepopulate from the values from the backend. I want to use socket io to read those values. Currently, I don't know what is the free backend like firebase I can use to mock those values. Also, how to read those values using socket io and update the fields in the NAT based on what it has read?
https://codesandbox.io/s/react-material-ui-forked-z3lfbs?file=/src/Components/Exercises/Nat.js:0-4650
Here is my code -
import React from "react";
import Switch from "#material-ui/core/Switch";
import { Grid } from "#material-ui/core";
import { Card, CardContent } from "#material-ui/core";
import { Typography } from "#material-ui/core";
import { makeStyles } from "#material-ui/core";
import { TextField } from "#material-ui/core";
import { Box } from "#material-ui/core";
import { Button } from "#material-ui/core";
import { withStyles } from "#material-ui/core/styles";
const AntSwitch = withStyles((theme) => ({
root: {
width: 39,
height: 22,
padding: 3,
display: "flex"
},
switchBase: {
padding: 2,
color: theme.palette.grey[500],
"&$checked": {
transform: "translateX(12px)",
color: theme.palette.common.white,
"& + $track": {
opacity: 1,
backgroundColor: theme.palette.primary.main,
borderColor: theme.palette.primary.main
}
}
},
thumb: {
width: 19,
height: 16,
boxShadow: "none"
},
track: {
border: `1px solid ${theme.palette.grey[500]}`,
borderRadius: 16 / 2,
opacity: 1,
backgroundColor: theme.palette.common.white
},
checked: {}
}))(Switch);
const useStyles = makeStyles({
switch: {
color: "black",
display: "flex"
},
button: {
display: "flex",
justifyContent: "flex-end",
alignItems: "right",
background: "#F04C23"
},
switchButton: {
background: "#91D7EA"
},
tabPanel: {
background: "#4D4D4D"
},
tab: {
textTransform: "none"
},
container: {
marginLeft: "2rem"
},
saveButtonContainer: {
color: "black",
display: "flex",
justifyContent: "flex-end",
padding: "0.5em",
marginTop: "1rem"
}
});
export default function Nat() {
const classes = useStyles();
const [keepAlive, setKeepAlive] = React.useState(false);
const keepAliveChecked = () => {
setKeepAlive((prev) => !prev);
};
const [ice, setIce] = React.useState(false);
const iceChecked = () => {
setIce((prev) => !prev);
};
const [turn, setTurn] = React.useState(false);
const turnChecked = () => {
setTurn((prev) => !prev);
};
return (
<React.Fragment>
<Card>
<CardContent className={classes.container}>
<Typography component="div">
<Grid container alignItems="center">
<Grid item xs={6}>
<h4>Keepalive</h4>
<Grid item className={classes.switch}>
<Grid item>Off</Grid>
<AntSwitch
size="small"
checked={keepAlive}
onChange={keepAliveChecked}
/>
<Grid item>On</Grid>
</Grid>
</Grid>
<Grid item xs={6}>
<h4>ICE</h4>
<Grid item className={classes.switch}>
<Grid item>Off</Grid>
<AntSwitch size="small" checked={ice} onChange={iceChecked} />
<Grid item>On</Grid>
</Grid>
</Grid>
<h4>TURN</h4>
<Grid item xs={12} className={classes.switch}>
<Grid item>Off</Grid>
<AntSwitch size="small" checked={turn} onChange={turnChecked} />
<Grid item>On</Grid>
</Grid>
<Grid item xs={6}>
<h4>STUN/TURN Server</h4>
<Grid item className={classes.switch}>
<TextField type="text" variant="outlined" size="small" />
</Grid>
</Grid>
<Grid item xs={6}>
<h4>STUN/TURN Server Port</h4>
<Grid item className={classes.switch}>
<TextField type="number" variant="outlined" size="small" />
</Grid>
</Grid>
<Grid item xs={6}>
<h4>TURN User Name</h4>
<Grid item className={classes.switch}>
<TextField type="text" variant="outlined" size="small" />
</Grid>
</Grid>
<Grid item xs={6}>
<h4>TURN Password</h4>
<Grid item className={classes.switch}>
<TextField type="password" variant="outlined" size="small" />
</Grid>
</Grid>
</Grid>
<Box className={classes.saveButtonContainer}>
<Button type="submit" className={classes.button}>
SAVE CHANGES
</Button>
</Box>
</Typography>
</CardContent>
</Card>
</React.Fragment>
);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Material-UI applying backgroundColor does not work

I have this code to apply the backgroundColor for my grid and it was working until today... It was black and now it just becomes white and I can't change the background color of the root element.
Is there any code that can overwrite this?
I got the code from here
https://github.com/mui-org/material-ui/blob/master/docs/src/pages/getting-started/templates/sign-in-side/SignInSide.js
const useStyles = makeStyles(theme => ({
root: {
height: '100%',
width: '100%',
backgroundColor: 'black'
},
<Grid container component='main' className={classes.root}>
// full code
import React, { useState } from 'react';
import { connect } from 'react-redux';
import history from '../../../history';
import { requestSignIn } from '../../../store/actions';
// import { Button, Container, Row, Col, FormControl, Dropdown } from 'react-bootstrap'
import Button from '#material-ui/core/Button';
import CssBaseline from '#material-ui/core/CssBaseline';
import TextField from '#material-ui/core/TextField';
import FormControlLabel from '#material-ui/core/FormControlLabel';
import Checkbox from '#material-ui/core/Checkbox';
import Link from '#material-ui/core/Link';
import Paper from '#material-ui/core/Paper';
import Box from '#material-ui/core/Box';
import Grid from '#material-ui/core/Grid';
import Typography from '#material-ui/core/Typography';
import { makeStyles } from '#material-ui/core/styles';
import Logo from '../../../../public/images/ic-logo-dark.png';
const useStyles = makeStyles(theme => ({
root: {
height: '100%',
width: '100%',
backgroundColor: 'black'
},
image: {
backgroundImage:
'url(https://media.giphy.com/media/kz76j0UjtPoE4WyhQn/giphy.gif)',
backgroundRepeat: 'no-repeat',
backgroundSize: 'cover',
backgroundPosition: 'center'
},
paper: {
margin: theme.spacing(8, 4),
display: 'flex',
flexDirection: 'column',
alignItems: 'center'
},
avatar: {
margin: theme.spacing(1)
},
form: {
width: '100%', // Fix IE 11 issue.
marginTop: theme.spacing(1),
color: 'orange'
},
submit: {
margin: theme.spacing(3, 0, 2)
}
}));
function Login() {
const classes = useStyles();
const [inputs, setInputs] = useState({
login: '',
password: ''
})
const [keepLogged, setKeepLogged] = useState(false)
const { login, password } = inputs
function handleChange(e) {
e.preventDefault();
const { name, value } = e.target;
setInputs(inputs => ({ ...inputs, [name]: value }));
console.log(`${login}`)
}
const loginUser = () => {
const { login, password } = this.inputs;
const { requestSignIn } = this.props;
requestSignIn({ login, password });
};
return (
<Grid container component='main' className={classes.root}>
<CssBaseline />
<Grid item xs={false} sm={4} md={7} className={classes.image} />
<Grid item xs={12} sm={8} md={5} component={Paper} elevation={6} square>
<div className={classes.paper}>
<div>
<img src={Logo} style={{ width: 300 }} />
</div>
<Typography component='h1' variant='h5'>
Sign in
</Typography>
<form className={classes.form} noValidate>
<TextField
variant='outlined'
margin='normal'
required
fullWidth
id='email'
label='Email Address'
value={login}
onChange={e => handleChange(e)}
name='login'
autoComplete='email'
autoFocus
/>
<TextField
variant='outlined'
margin='normal'
required
fullWidth
name='password'
label='Password'
value={password}
onChange={e => handleChange(e)}
type='password'
id='password'
autoComplete='current-password'
/>
<FormControlLabel
control={<Checkbox value='remember' color='primary' />}
label='Remember me'
/>
<Button
type='submit'
fullWidth
variant='contained'
color='primary'
value='Log In'
className={classes.submit}
onClick={() => this.loginUser}
>
Sign In 🙂
</Button>
<Grid container>
<Grid item xs>
<Link href='#' variant='body2'>
Forgot password?
</Link>
</Grid>
<Grid item>
<Link
variant='body2'
onClick={() => history.push('/registration')}
>
{"Don't have an account? Sign Up"}
</Link>
</Grid>
</Grid>
<Box mt={5}>
<Copyright />
</Box>
</form>
</div>
</Grid>
</Grid>
);
}
const mapDispatchToProps = dispatch => ({
requestSignIn: data => dispatch(requestSignIn(data))
});
export default connect(null, mapDispatchToProps)(Login);
I have same problem. Everything else is working but letterSpacing and backgroundColor is not working.
But if I put style={{color: 'white', backgroundColor: '#e91e63'}}, it works.
<Card className={classes.cardStyle} style={{ color: 'white', backgroundColor: '#e91e63' }}>
ABC </Card>
Declare a new style in useStyles
const useStyles = makeStyles(theme => ({
color: {
backgroundColor: 'black'
}
and apply this style to your third grid.
<Grid container component='main' className={classes.root}>
<CssBaseline />
<Grid item xs={false} sm={4} md={7} className={classes.image} />
<Grid
item
xs={12}
sm={8}
md={5}
component={Paper}
elevation={6}
square
className={classes.color}
>

PropTypes validation failed when executing the application

I'm trying to use react hooksin a simple app.
This is a reference to the code I wrote:
MyApp
const styles = theme => ({
root: {
...theme.mixins.gutters(),
paddingTop: theme.spacing.unit * 2,
paddingBottom: theme.spacing.unit * 2
},
button: {
margin: theme.spacing.unit
}
});
function PaperSheet(props) {
const [open, setOpen] = useState(false);
const { classes } = props;
const { title, data } = props;
return (
<div>
<Paper className={classes.root} elevation={1}>
<Typography align="center" variant="h3" component="h3">
{title}
</Typography>
<Typography align="center" component="p">
What is the result of :
{`${math.ceil(data[0])} + ${math.ceil(data[1])}`}
</Typography>
<TextField
id="outlined-full-width"
label="Result"
style={{ margin: 8 }}
fullWidth
margin="normal"
variant="outlined"
InputLabelProps={{
shrink: true,
required: true
}}
/>
<Button
variant="contained"
color="primary"
className={classes.button}
onClick={() => {
setOpen(true);
}}
>
Submit
</Button>
<Modal open={open} closeModel={() => setOpen(false)} />
</Paper>
</div>
);
}
PaperSheet.propTypes = {
classes: PropTypes.objectOf(PropTypes.string.isRequired).isRequired,
title: PropTypes.string.isRequired,
data: PropTypes.arrayOf(PropTypes.number.isRequired).isRequired
};
function getModalStyle() {
const top = 50;
const left = 50;
return {
top: `${top}%`,
left: `${left}%`,
transform: `translate(-${top}%, -${left}%)`
};
}
const styles = theme => ({
paper: {
position: "absolute",
width: theme.spacing.unit * 50,
backgroundColor: theme.palette.background.paper,
boxShadow: theme.shadows[5],
padding: theme.spacing.unit * 4
}
});
const SimpleModal = props => {
const { classes, open, closeModel } = props;
console.log("open: ", open);
return (
<div>
<Modal
aria-labelledby="simple-modal-title"
aria-describedby="simple-modal-description"
open={open}
onClose={closeModel}
>
<div style={getModalStyle()} className={classes.paper}>
<Typography variant="h6" id="modal-title">
Text in a modal
</Typography>
<Typography variant="subtitle1" id="simple-modal-description">
success
</Typography>
<SimpleModalWrapped />
</div>
</Modal>
</div>
);
};
SimpleModal.propTypes = {
classes: PropTypes.shape({ paper: PropTypes.string }).isRequired,
open: PropTypes.bool.isRequired,
closeModel: PropTypes.func.isRequired
};
// We need an intermediary variable for handling the recursive nesting.
const SimpleModalWrapped = withStyles(styles)(SimpleModal);
When I run the app and I click the Submit button I get this error:
Warning: Failed prop type: The prop `open` is marked as required in `SimpleModal`, but its value is `undefined`.
in SimpleModal (created by WithStyles(SimpleModal))
in WithStyles(SimpleModal) (created by SimpleModal)
Is this error due to the first render of the modal component? If so, how can I fix it?
It seems that the problem is caused by a recursive call of <SimpleModalWrapped /> on line 46 of modal.jsx file.
No props are being passed to this component and this triggers PropType warnings.

Resources