React JS with Material UI - When using withStyles this.props is undefined - javascript

When I run the code below I expected that styles would be injected inside props, but I always end up getting undefined props.
I am not providing any props to this component.
const styles = theme => ({
root: {
'& .MuiTextField-root': {
margin: theme.spacing(1),
width: '25ch',
},
},
});
class Editor extends React.Component {
render() {
const { classes } = this.props;
return (
<div className="editor">
<form className={classes.root} noValidate autoComplete="off">
<TextField id="standard-basic" label="Standard" />
<Button variant="contained" color="primary">
Hello World
</Button>
</form>
</div>
);
}
}
export default withStyles(styles)(Editor);

Hi you can use makeStyles from '#material-ui/core/styles'. Please check complete example below:
import React from 'react';
import {makeStyles} from '#material-ui/core/styles';
import Grid from '#material-ui/core/Grid';
import FormLabel from '#material-ui/core/FormLabel';
import FormControlLabel from '#material-ui/core/FormControlLabel';
import RadioGroup from '#material-ui/core/RadioGroup';
import Radio from '#material-ui/core/Radio';
import Paper from '#material-ui/core/Paper';
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
},
paper: {
height: 140,
width: 100,
},
control: {
padding: theme.spacing(2),
},
}));
export default function SpacingGrid() {
const [spacing, setSpacing] = React.useState(2);
const classes = useStyles();
const handleChange = (event) => {
setSpacing(Number(event.target.value));
};
return (
<Grid container className={classes.root} spacing={2}>
<Grid item xs={12}>
<Grid container justify="center" spacing={spacing}>
{[0, 1, 2].map((value) => (
<Grid key={value} item>
<Paper className={classes.paper}/>
</Grid>
))}
</Grid>
</Grid>
<Grid item xs={12}>
<Paper className={classes.control}>
<Grid container>
<Grid item>
<FormLabel>spacing</FormLabel>
<RadioGroup
name="spacing"
aria-label="spacing"
value={spacing.toString()}
onChange={handleChange}
row
>
{[0, 1, 2].map((value) => (
<FormControlLabel
key={value}
value={value.toString()}
control={<Radio/>}
label={value.toString()}
/>
))}
</RadioGroup>
</Grid>
</Grid>
</Paper>
</Grid>
</Grid>
);
}
Source

Related

TypeError: Cannot read properties of undefined (reading 'map') react

I'm trying to get a Tv show to display on multiple cards. I'm just using one Tv show before I start adding any more. So it should basically display one tv show on all the cards.
The error is coming from the tvList.js.
tvList.js
import React from "react";
import Tv from "../tvCard/";
import Grid from "#material-ui/core/Grid";
const TvList = (props) => {
let tvCards = props.tvshows.map((m) => (
<Grid key={m.id} item xs={12} sm={6} md={4} lg={3} xl={2}>
<Tv key={m.id} tv={m} />
</Grid>
));
return tvCards;
};
export default TvList;
The Tv card seems to be fine and is working in my storybook.
tvCard.js
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import Card from "#material-ui/core/Card";
import CardActions from "#material-ui/core/CardActions";
import CardContent from "#material-ui/core/CardContent";
import CardMedia from "#material-ui/core/CardMedia";
import CardHeader from "#material-ui/core/CardHeader";
import Button from "#material-ui/core/Button";
import Typography from "#material-ui/core/Typography";
import FavoriteIcon from "#material-ui/icons/Favorite";
import CalendarIcon from "#material-ui/icons/CalendarTodayTwoTone";
import StarRateIcon from "#material-ui/icons/StarRate";
import IconButton from "#material-ui/core/IconButton";
import Grid from "#material-ui/core/Grid";
import img from '../../images/tv-poster-placeholder.png'
const useStyles = makeStyles({
card: { maxWidth: 345 },
media: { height: 500 },
avatar: {
backgroundColor: "rgb(255, 0, 0)",
},
});
export default function TvCard(props) {
const classes = useStyles();
const tv = props.tv;
return (
<Card className={classes.card}>
<CardHeader className={classes.header} title={tv.name} />
<CardMedia
className={classes.media}
image={
tv.poster_path
? `https://image.tmdb.org/t/p/w500/${tv.poster_path}`
: img
}
/>
<CardContent>
<Grid container>
<Grid item xs={6}>
<Typography variant="h6" component="p">
<CalendarIcon fontSize="small" />
{tv.first_air_date}
</Typography>
</Grid>
<Grid item xs={6}>
<Typography variant="h6" component="p">
<StarRateIcon fontSize="small" />
{" "} {tv.vote_average}{" "}
</Typography>
</Grid>
</Grid>
</CardContent>
<CardActions disableSpacing>
<IconButton aria-label="add to favorites" onClick={null}>
<FavoriteIcon color="primary" fontSize="large" />
</IconButton>
<Button variant="outlined" size="medium" color="primary">
More Info ...
</Button>
</CardActions>
</Card>
);
}
tvPage.js
import React from "react";
import Header from "../components/headerTvList";
import FilterCard from "../components/filterTvCard";
import Grid from "#material-ui/core/Grid";
import { makeStyles } from "#material-ui/core/styles";
import TvList from "../components/tvList";
const useStyles = makeStyles({
root: {
padding: "20px",
},
});
const TvListPage = (props) => {
const classes = useStyles();
const tvshows = props.tvshows;
return (
<Grid container className={classes.root}>
<Grid item xs={12}>
<Header title={"Discover Tv Shows"} />
</Grid>
<Grid item container spacing={5}>
<Grid key="find" item xs={12} sm={6} md={4} lg={3} xl={2}>
<FilterCard />
</Grid>
<TvList tvshows={tvshows}></TvList>
</Grid>
</Grid>
);
};
export default TvListPage;
src/index.js
import React from "react";
import ReactDOM from "react-dom";
import TvPage from "./pages/tvPage";
const sample = {
"backdrop_path": "/wAEWZm2pSopAbqE5dQWE0ET8aR5.jpg",
"first_air_date": "2021-01-08",
"genre_ids": [
10759,
10765,
99
],
"id": 114695,
"name": "Marvel Studios: Legends",
"origin_country": [
"US"
],
"original_language": "en",
"original_name": "Marvel Studios: Legends",
"overview": "Revisit the epic heroes, villains and moments from across the MCU in preparation for the stories still to come. Each dynamic segment feeds directly into the upcoming series — setting the stage for future events. This series weaves together the many threads that constitute the unparalleled Marvel Cinematic Universe.",
"popularity": 140.788,
"poster_path": "/EpDuYIK81YtCUT3gH2JDpyj8Qk.jpg",
"vote_average": 7.6,
"vote_count": 515
}
const tvshows = [sample, sample, sample, sample, sample, sample, sample];
const App = () => {
return (
<TvPage tvshows={tvshows} />
);
};
ReactDOM.render(<App />, document.getElementById("root"));
It could be an with the tvPage component.
const tvshows = props.tvshows;
Here the value of tvshows might be empty initially. I'd suggest i your TvList component do an null check.
const TvList = (props) => {
let tvCards = props.tvshows?.map((m) => (
<Grid key={m.id} item xs={12} sm={6} md={4} lg={3} xl={2}>
<Tv key={m.id} tv={m} />
</Grid>
));
return tvCards;
};
The ? is an [optional chaining] operator(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining).
The error is that for some reason, props.tvshows is undefined within TvList, even though it should be passed down from App to TvPage to TvList. At some point down the line, tvshows is lost.
I would suggest logging all instances of tvshows, starting from when it is first defined in App, then logging in TvPage, then TvList, to see where exactly the problem is coming from. Once you've found it, do some debugging to make the problem stop.

React js material ui Grid responsive

As you can see from the image on the left I have a map with the controls, on the right I have a series of fields (last update, a table and an input field).
What I would like to do is that when it reaches a certain size (device example) the right side goes down under the map, the map then takes all the available space.
As you can see from the image when you resize a part of the table you do not see, you have to scroll.
Can you give me a hand?
In the original project I also use:
"tailwindcss": "1.2.0",
"tailwindcss-dir": "4.0.0"
Link: codesandbox
Code:
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import {
Grid,
TextField,
Paper,
Typography,
Tooltip,
Chip
} from "#material-ui/core";
import { red, teal } from "#material-ui/core/colors";
import Map from "./Map";
import ToggleButtonMap from "./ToggleButtonMap";
import DataTable from "react-data-table-component";
import "./styles.css";
const useStyles = makeStyles((theme) => ({
root: {},
paper: {
display: "flex",
border: `1px solid ${theme.palette.divider}`,
flexWrap: "wrap",
padding: 10
},
control: {}
}));
export default function App() {
const [state, setState] = React.useState({
historyParking: [
{
idPs: "7ff2-4e5d-b164-661b511e609e-1",
free: false,
latitude: 33,
longitude: 10,
timeCurrent: "23/10/2020 15:13:23"
},
{
idPs: "7ff2-4e5d-b164-661b511e609e-1",
free: true,
latitude: 33,
longitude: 10,
timeCurrent: "23/10/2020 15:13:23"
}
]
});
const { historyParking } = state;
const classes = useStyles();
const columns = [
{
name: "Name",
selector: "idPs",
cell: ({ idPs }) => (
<Tooltip title={`${idPs}`} placement="right-start" arrow>
<span>{shortCode(camPlace(idPs).idPs)}</span>
</Tooltip>
)
},
{
name: "Place",
selector: "idPs",
cell: ({ idPs }) => camPlace(idPs).place
},
{
name: "Status",
selector: "free",
cell: ({ free }) => (
<div>
<Chip
variant="outlined"
style={{
color: free ? teal["600"] : red["600"],
borderColor: free ? teal["600"] : red["600"]
}}
label={`${fixName(free?.toString())}`}
size="small"
/>
</div>
)
},
{
name: "Last update",
selector: "timeCurrent",
cell: ({ timeCurrent }) => (
<Tooltip title={`${timeCurrent}`} placement="right-start" arrow>
<span>{timeCurrent}</span>
</Tooltip>
)
}
];
const shortCode = (code, left = 10, right = 10) => {
return `${code.substring(0, left)}...${code.substring(
code.length - right,
code.length
)}`;
};
const fixName = (name) => {
return name
?.replace("_", " ")
.toLowerCase()
.split(" ")
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(" ");
};
const camPlace = (a) => {
const idPs = a.split("-");
const place = idPs.pop();
return { idPs: idPs.join("-"), place };
};
return (
<>
<Grid container spacing={2}>
<Grid item xs={8}>
<Paper elevation={1} className={classes.paper}>
<Grid container spacing={2}>
<Grid item>
<ToggleButtonMap />
</Grid>
<Grid item xs={12} sm={12} className="h-512">
<Map />
</Grid>
</Grid>
</Paper>
</Grid>
<Grid item xs={4}>
<Grid container direction="column" spacing={1}>
<Grid item>
<TextField
id="city_zone"
variant="outlined"
size="small"
></TextField>
</Grid>
<Grid item>
<Typography component="div">
Last update: 23/10/2020 16:31:35
</Typography>
</Grid>
<Grid item>
<div
style={{
border: "1px solid #dadce0",
backgroundColor: "#fff",
marginTop: 5
}}
>
<DataTable
title={"History"}
columns={columns}
data={historyParking}
highlightOnHover
defaultSortField="timeCurrent"
defaultSortAsc={false}
pagination
paginationPerPage={6}
/>
</div>
</Grid>
</Grid>
</Grid>
</Grid>
</>
);
}
This might be what you are looking for
<Grid item xs={8} sm={12}>
<Paper elevation={1} className={classes.paper}>
<Grid container spacing={2}>
<Grid item>
<ToggleButtonMap />
</Grid>
<Grid item xs={12} className="h-512">
<Map />
</Grid>
</Grid>
</Paper>
</Grid>

I cant not used compose withRouter and withAlert Reactjs

I cant not use compose withRouter and withAlert
It's work only withRouter but I cant used this.props.alert.success...............................................................................................................................
It show error
Unhandled Rejection (TypeError): Cannot read property 'success' of undefined
import React from "react";
import Container from "#material-ui/core/Container";
import Typography from "#material-ui/core/Typography";
import Grid from "#material-ui/core/Grid";
import { withRouter } from "react-router-dom";
import Paper from "#material-ui/core/Paper";
import Button from "#material-ui/core/Button";
import { withAlert } from "react-alert";
import Select from "#material-ui/core/Select";
import InputLabel from "#material-ui/core/InputLabel";
import MenuItem from "#material-ui/core/MenuItem";
import FormControl from "#material-ui/core/FormControl";
import { compose } from "redux";
import { firestore } from "../../firebase/firebase.utils";
class Updatestatusproperty extends React.Component {
constructor(props) {
super(props);
this.state = {
id: this.props.match.params.id,
status:1
};
}
handleSubmit = async (event) => {
event.preventDefault();
this.props.alert.success("อัพเดทสถานะบ้านเสร็จสิ้น");
// firestore
// .collection("house")
// .doc(this.state.id)
// .update({status:this.state.status})
// .then(() => {
// this.props.alert.success("อัพเดทสถานะบ้านเสร็จสิ้น");
// })
// .catch((err) => {
// console.log(err)
// });
};
handleChange = (event) => {
this.setState({ status: event.target.value });
console.log( event.target.value )
};
render() {
return (
<Container
maxWidth="md"
style={{ paddingTop: "4%", paddingBottom: "4%" }}
>
<Paper
variant="outlined"
style={{
backgroundColor: "#f2f2f2",
backgroundPosition: "center",
backgroundSize: "cover",
backgroundRepeat: "no-repeat",
padding: "4%",
}}
>
<Grid container spacing={3}>
<Grid item xs={6}>
<Typography variant="h4">{"อัพเดทสถานะ"}</Typography>
</Grid>
<Grid item xs={12}>
<Typography variant="h6">{"อัพเดทสถานะบ้าน"}</Typography>
</Grid>
<Grid item xs={4}>
<FormControl fullWidth>
<InputLabel id="demo-simple-select-label">
อัพเดทสถานะบ้าน
</InputLabel>
<Select name="sizefamily" onChange={this.handleChange} value={this.state.status}>
<MenuItem value={1}>พร้อมขาย</MenuItem>
<MenuItem value={2}>อยู่ระหว่างเจรจา</MenuItem>
<MenuItem value={3}>ขายออกไปแล้ว</MenuItem>
</Select>
</FormControl>
</Grid>
<Grid item xs={3}>
<Button
type="submit"
variant="contained"
color="primary"
fullWidth
size="large"
style={{ backgroundColor: "#55aa54", marginTop: "3.5%" }}
onClick={this.handleSubmit}
>
อัพเดทสถานะ
</Button>
</Grid>
</Grid>
</Paper>
</Container>
);
}
}
export default compose(withRouter(Updatestatusproperty),withAlert());
You are using the compose function incorrectly.
You need to pass the HOCs, withRoute as arguments to it without calling it like below
export default compose(withRouter,withAlert())(Updatestatusproperty);

What is the problem of glitch when scrolling using react-window?

I want to do row virtualization when scrolling (so that data is shown when scrolling)
But when scrolling, now the terrible glitches appear
Tell me what is the problem?
project - male-wind.surge.sh
A component with a table (react-window is used there):
import React, { Component } from "react";
import { connect } from "react-redux";
import actions from "../../actions";
import PropTypes from "prop-types";
import sort from "./sort";
import { FixedSizeList } from 'react-window';
function TitleColumn(data) {
return (
<Grid item xs={1}>
<Box className="title_elem">
<h3
className="table_title-text"
onClick={sort.bind(null, `${data.title.toLowerCase()}`, data.props)}
>
{data.title}
</h3>
{data.props.fourthData.data === `${data.title.toLowerCase()}` ? (
<p>{data.props.fifthData.data}</p>
) : null}
</Box>
</Grid>
);
}
class Table extends Component {
render() {
const data = this.props.info;
const Row = ({ index, style}) => {
return (
<Grid container className="table_row">
<Grid item xs={1}>
<Box className="table_elem name_elem">{data[index].name}</Box>
</Grid>
<Grid item xs={1}>
<Box className="table_elem job_elem">{data[index].job}</Box>
</Grid>
<Grid item xs={1}>
<Box className="table_elem city_elem">{data[index].city}</Box>
</Grid>
<Grid item xs={1}>
<Box className="table_elem country_elem">{data[index].country}</Box>
</Grid>
<Grid item xs={1}>
<Box className="table_elem latitude_elem">{data[index].latitude}</Box>
</Grid>
<Grid item xs={1}>
<Box className="table_elem longitude_elem">{data[index].longitude}</Box>
</Grid>
<Grid item xs={1}>
<Box className="table_elem date_elem">
{`${data[index].date.toLocaleString("en", {
year: "numeric",
month: "long",
day: "numeric"
})}`}
</Box>
</Grid>
</Grid>
)
};
return (
<Grid
container
className="developer_block-time_feature time_feature_block"
>
<Grid container className="table_title">
<TitleColumn props={this.props} title="Name" />
<TitleColumn props={this.props} title="Job" />
<TitleColumn props={this.props} title="City" />
<TitleColumn props={this.props} title="Country" />
<TitleColumn props={this.props} title="Latitude" />
<TitleColumn props={this.props} title="Longitude" />
<TitleColumn props={this.props} title="Date" />
</Grid>
<FixedSizeList <---------------use react-window
height={500}
itemSize={60}
itemCount={data.length}
className="list-container"
>
{Row}
</FixedSizeList>
</Grid>
);
}
}
Table.propTypes = {
fourthData: PropTypes.object.isRequired,
fifthData: PropTypes.object.isRequired
};
const mapStateToProps = store => {
return {
firstData: store.firstData,
secondData: store.secondData,
thirdData: store.thirdData,
fourthData: store.fourthData,
fifthData: store.fifthData
};
};
const mapDispatchToProps = dispatch => {
return {
setData: data => dispatch(actions.setData(data)),
changeSearchData: searchData =>
dispatch(actions.changeSearchData(searchData)),
changeSort: sort => dispatch(actions.changeSort(sort)),
setSortTitle: sortField => dispatch(actions.setSortTitle(sortField)),
changeArrow: arrow => dispatch(actions.changeArrow(arrow))
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Table);
I try to use this solution, but it does not help - https://github.com/bvaughn/react-virtualized/issues/1327
you have to apply the style passed by list for list element rendering which sets height, width and top attributes. you can do as below
const Row = ({ index, style}) => {
return (
<Grid container className="table_row" style={style}>
<Grid item xs={1}>
<Box className="table_elem name_elem">{data[index].name}</Box>
</Grid>....…..

Trouble with Grid Layout in React Material UI

I'm trying to achieve a specific layout using the Material UI Grid Component, but I just cannot for the life of me get it right.
I have a Dialog where I want the Layout to end up like this:
Where the blue box contains some information about a project, the green box will contain some sort of media and the yellow box will contain a descriptive text.
But currently, with this code, it ends up like this:
<Grid xl={12}>
<Grid spacing={0} xs={2}>
<Grid container direction="column">
<Grid item xs={1}>
{ this.getGridItems("Platforms", data["platforms"].split(','), true) }
</Grid>
<Grid item xs={1}>
{ this.getGridItems("Engines", data["engines"].split(','), true) }
</Grid>
<Grid item xs={1}>
{ this.getGridItems("Frameworks", data["frameworks"].split(','), true) }
</Grid>
<Grid item xs={1}>
{ this.getGridItems("Languages", data["languages"].split(',')) }
</Grid>
<Grid item xs={1}>
{ this.getGridItems("Roles", data["roles"].split(',')) }
</Grid>
</Grid>
</Grid>
<Grid spacing={0} xl={10}>
<Grid container>
<Grid item xl={9}>
<h1>Image Goes Here</h1>
</Grid>
<Grid item xl={3}>
<h1>Description</h1>
{ data["description"] }
</Grid>
</Grid>
</Grid>
</Grid>
I cannot quite figure out where I went wrong as I can't wrap my head around how the Grid layout works. Please help?
If it's necessary, here is the code for getGridItems():
getGridItems = (header, data, chips) => {
let list = [];
let fontSize = 11;
list.push(
<h5>{ header }</h5>
);
if(data.length > 0 && data[0] !== '') {
if(chips !== undefined && true) {
data.forEach(value => {
let chipData = ChipConstants[value];
list.push(
<Grid item xs>
<Chip
style={{ fontSize: fontSize}}
avatar={
<Avatar
style={{ width: 24, height: 24 }}
alt={chipData["avatar"]["alt"]}
src={require("../img/avatars/"+chipData["avatar"]["img"])}
/>}
label={chipData["avatar"]["alt"]}
className={styles.chip}
/>
</Grid>
);
});
} else {
data.forEach(value => {
list.push(
<Grid item xs style={{ fontSize: fontSize}}>
{ value }
</Grid>
);
});
}
} else {
list.push(
<Grid item xs style={{ fontSize: fontSize}}>
None
</Grid>
);
}
return list;
};
I'm not really seeing how your current code relates to what you want, so instead of trying to correct your current code, I'll just provide a starting point that provides the basic structure of what you want.
If you have specific questions about how the Grid in my code works, I'll elaborate as needed.
index.js
import React from "react";
import ReactDOM from "react-dom";
import CssBaseline from "#material-ui/core/CssBaseline";
import Button from "#material-ui/core/Button";
import MyDialog from "./MyDialog";
class App extends React.Component {
state = {
open: false
};
handleClickOpen = () => {
this.setState({ open: true });
};
handleClose = () => {
this.setState({ open: false });
};
render() {
return (
<>
<CssBaseline />
<Button variant="contained" onClick={this.handleClickOpen}>
Open Dialog
</Button>
<MyDialog open={this.state.open} handleClose={this.handleClose} />
</>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
MyDialog.js
import React from "react";
import Grid from "#material-ui/core/Grid";
import Dialog from "#material-ui/core/Dialog";
import IconButton from "#material-ui/core/IconButton";
import CloseIcon from "#material-ui/icons/Close";
import { withStyles } from "#material-ui/core/styles";
const styles = {
root: {
height: "100%"
},
project: {
backgroundColor: "lightblue",
height: "100%"
},
right: {
height: "100%"
},
media: {
backgroundColor: "lightgreen",
height: "70%"
},
desc: {
backgroundColor: "yellow",
height: "30%"
}
};
const MyDialog = props => {
return (
<Dialog fullScreen open={props.open} onClose={props.handleClose}>
<Grid container className={props.classes.root}>
<Grid item xs={3} className={props.classes.project}>
<IconButton
color="inherit"
onClick={props.handleClose}
aria-label="Close"
>
<CloseIcon />
</IconButton>
Project
</Grid>
<Grid item xs={9}>
<Grid container direction="column" className={props.classes.right}>
<Grid item className={props.classes.media}>
Media
</Grid>
<Grid item className={props.classes.desc}>
Description
</Grid>
</Grid>
</Grid>
</Grid>
</Dialog>
);
};
export default withStyles(styles)(MyDialog);
Here it is in a CodeSandbox you can experiment with:

Categories