Cannot read props of undefined - javascript

I am trying to add class form control for my select statement. However there is a problem which occurs. It shows props are undefined.
Here is the code:
const useStyles = makeStyles({
root: {
width: "100%",
maxWidth: 500
}
});
const classes = {
formControl: {
margin: this.props.theme.spacing(1),
minWidth: 120,
},
selectEmpty: {
marginTop: this.props.theme.spacing(2),
},
};
export class FormUserDetails extends Component {
constructor(props) {
super(props);
this.state = { KPI: [], addModalShow: false,age: "",
name: "hai" };
}
continue = e => {
e.preventDefault();
if (document.getElementById("Title").value.length < 5) {
document.getElementById("title").style.visibility = "visible";
document.getElementById("Title").style.border = "1px solid red";
// keep form from submitting
} else if (document.getElementById("Details").value.length < 10) {
document.getElementById("details").style.visibility = "visible";
document.getElementById("Details").style.border = "1px solid red";
// keep form from submitting
} else if (document.getElementById("What").value.length < 10) {
document.getElementById("what").style.visibility = "visible";
document.getElementById("What").style.border = "1px solid red";
// keep form from submitting
} else if (document.getElementById("Why").value.length < 10) {
document.getElementById("why").style.visibility = "visible";
document.getElementById("Why").style.border = "1px solid red";
// keep form from submitting
} else if (document.getElementById("How").value.length < 10) {
document.getElementById("how").style.visibility = "visible";
document.getElementById("How").style.border = "1px solid red";
// keep form from submitting
} else if (document.getElementById("Implementation_Status").value == "") {
document.getElementById("status").style.visibility = "visible";
document.getElementById("Status").style.border = "1px solid red";
// keep form from submitting
} else if (document.getElementById("Cost").value.length < 1) {
document.getElementById("cost").style.visibility = "visible";
document.getElementById("Cost").style.border = "1px solid red";
// keep form from submitting
} else if (document.getElementById("Benefits").value.length < 10) {
document.getElementById("benefits").style.visibility = "visible";
document.getElementById("Benefits").style.border = "1px solid red";
// keep form from submitting
} else {
// else form is good let it submit, of course you will
// probably want to alert the user WHAT went wrong.
this.props.nextStep();
}
};
handleSubmit(event) {
event.preventDefault();
fetch("https://localhost:44384/api/Details", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({
TBD_ID: null,
TBD_TITLE: event.target.Title.value,
TBD_WHAT: event.target.What.value,
TBD_WHY: event.target.Why.value,
TBD_HOW: event.target.How.value,
TBD_STAGE: 1,
TBD_STATUS: event.target.Implementation_Status.value,
TBD_COST: event.target.Cost.value,
TBD_BENEFIT: event.target.Benefits.value,
TBD_BENEFIT_TYPE: 1,
TBD_FL_ACTIVE: null,
TBD_CRT_ID: null,
TBD_CRT_TS: null,
TBD_UPD_ID: null,
TBD_UPD_TS: null,
TBD_VALUE_ID: 2
})
})
.then(res => res.json())
.then(
result => {
alert(result);
},
error => {
alert("Failed");
}
);
}
//1
handleChangeRows = idx => e => {
const { Kpi_Before, value } = e.target;
const rows = [...this.state.rows];
rows[idx] = {
[Kpi_Before]: value
};
this.setState({
rows
});
};
//2
handleAddRow = () => {
const item = {
KPI_Before: "",
UOM_Before: "",
Base_Before: "",
Target_Before: "",
dateTime: ""
};
this.setState({
rows: [...this.state.rows, item]
});
};
//3
handleRemoveRow = () => {
this.setState({
rows: this.state.rows.slice(0, -1)
});
};
render() {
const { values, handleChange } = this.props;
const { deps } = this.state;
let { values1 } = this.state;
let addModalClose = () => this.setState({ addModalShow: false });
return (
<MuiThemeProvider theme={theme}>
<React.Fragment>
<div className={useStyles.root}>
<Grid item xs={12}>
<AppBar position="static">
<Toolbar>
<NavLink to="dashboard">
<DashboardIcon style={{ color: "white" }} />
</NavLink>
<Typography
align="center"
style={{ width: "100%", alignItems: "center" }}
>
Best Practices Management System
</Typography>
</Toolbar>
</AppBar>
</Grid>
</div>
<br />
<Form onSubmit={this.handleSubmit} style={{ marginLeft: "5%" }}>
<Grid container>
<Grid item xs={12}>
<TextField
label="Title"
variant="outlined"
size="small"
name="Title"
id="Title"
placeholder="Enter the Title of the Best Practice"
onChange={handleChange("Title")}
defaultValue={values.Title}
multiline
rows={1}
rowsMax={4}
style={{ width: "95%" }}
/>
<label
id="title"
style={{ visibility: "hidden", color: "red" }}
>
Title must be atleast 5 characters long
</label>
</Grid>
</Grid>
<Grid container>
<Grid item xs={6}>
<TextField
placeholder="Enter the details of the Best Practice"
label="Details of Best Practice"
id="Details"
size="small"
name="Details"
onChange={handleChange("Details")}
defaultValue={values.Details}
style={{ width: "90%" }}
variant="outlined"
multiline
rows={2}
rowsMax={4}
/>
<label
id="details"
style={{ visibility: "hidden", color: "red" }}
>
Details of Best Practice must be atleast 10 characters long
</label>
</Grid>
<Grid item xs={6}>
<TextField
placeholder="What is the Best Practice?"
label="What is the Best Practice"
size="small"
id="What"
name="What"
onChange={handleChange("What")}
defaultValue={values.What}
style={{ width: "90%" }}
variant="outlined"
multiline
rows={2}
rowsMax={4}
/>
<label id="what" style={{ visibility: "hidden", color: "red" }}>
What is the Best Practice must be atleast 10 characters long
</label>
</Grid>
</Grid>
<Grid container>
<Grid item xs={6}>
<TextField
placeholder="Why was the Best Practice Implemented"
label="Why was the Best Practice Implemented"
size="small"
name="Why"
id="Why"
onChange={handleChange("Why")}
defaultValue={values.Why}
style={{ width: "90%" }}
variant="outlined"
multiline
rows={2}
rowsMax={4}
/>
<label id="why" style={{ visibility: "hidden", color: "red" }}>
Why was the Best Practice implemented must be atleast 10
characters long
</label>
</Grid>
<Grid item xs={6}>
<TextField
placeholder="How was the Best Practice Implemented"
label="How was the Best Practice Implemented"
size="small"
name="How"
id="How"
onChange={handleChange("How")}
defaultValue={values.How}
style={{ width: "90%" }}
variant="outlined"
multiline
rows={2}
rowsMax={4}
/>
<label id="how" style={{ visibility: "hidden", color: "red" }}>
How was the Best Practice implemented must be atleast 10
characters long
</label>
</Grid>
</Grid>
<Grid container>
<Grid item xs={6}>
<FormControl id="Status" style={{ width: "90%" }} size="small">
<AddProcessModal
show={this.state.addModalShow}
onHide={addModalClose}
/>
<InputLabel
htmlFor="Implementation_Status"
id="Status"
style={{
marginLeft: 10,
top: "50%",
transform: "translate(0,-50%"
}}
>
Implementation Status
</InputLabel>
<Select
labelId="Implementation_Status"
name="Status"
id="Status"
onChange={handleChange("Status")}
defaultValue={values.Status}
variant="outlined"
inputProps={{
id: "Implementation_Status",
name: "age"
}}
>
<MenuItem value="1">Implemented</MenuItem>
<MenuItem value="2">Implementation in Progress</MenuItem>
<MenuItem value="3">Not Implemented</MenuItem>
</Select>
</FormControl>
<label
id="status"
style={{ visibility: "hidden", color: "red" }}
>
Implementation Status cannot be blank
</label>
</Grid>
<Grid item xs={6}>
<Form.Group controlId="TBD_COST">
<TextField
placeholder="Cost of Implementation of the Best Practice"
label="Cost of Implementation"
name="Cost"
id="Cost"
size="small"
onChange={handleChange("Cost")}
defaultValue={values.Cost}
style={{ width: "90%" }}
variant="outlined"
/>
<label
id="cost"
style={{ visibility: "hidden", color: "red" }}
>
Cost of Implementation cannot be left blank
</label>
</Form.Group>
</Grid>
</Grid>
<Grid container>
<Grid item xs={6}>
<TextField
placeholder="Benefits of the Best Practice"
label="Benefits of the Best Practice"
size="small"
name="Benefits"
id="Benefits"
onChange={handleChange("Benefits")}
defaultValue={values.Benefits}
style={{ width: "90%" }}
variant="outlined"
multiline
rows={2}
rowsMax={4}
/>
<label
id="benefits"
style={{ visibility: "hidden", color: "red" }}
>
Benefits must be at least 10 characters long
</label>
</Grid>
<Grid item xs={6}>
<FormControl className={classes.formControl} id="Process" style={{ width: "78%" }} size="small">
<InputLabel
htmlFor="Process"
id="Process"
style={{
marginLeft: 10,
top: "50%",
transform: "translate(0,-50%"
}}
>
Process
</InputLabel>
<Select
labelId="Process"
name="Process"
id="Process"
value={this.state.Process}
defaultValue={values.Process}
onChange={() => this.setState({ addModalShow: true })}
variant="outlined"
InputLabelProps={{
shrink: this.state.value ? true : false
}}
inputProps={{
name: "Process",
id: "Process"
}}
>
<option aria-label='None' value='' />
<option value={10}>Ten</option>
<option value={20}>Twenty</option>
<option value={30}>Thirty</option>
</Select>
</FormControl>
<Button
variant="outlined"
color="primary"
onClick={() => this.setState({ addModalShow: true })}
size="small"
style={styles.button2}
>
+
</Button>
<label
id="process"
style={{ visibility: "hidden", color: "red" }}
>
Process cannot be blank
</label>
</Grid>
</Grid>
<Grid
direction="row"
justify="right"
alignItems="right"
className="text-right"
style={{ width: "96%" }}
>
<Button
variant="contained"
size="small"
color="primary"
style={styles.button}
onClick={this.continue}
className="float-right"
>
Continue
</Button>
<Button
variant="contained"
size="small"
color="primary"
type="submit"
style={styles.button1}
>
Submit
</Button>
</Grid>
</Form>
</React.Fragment>
</MuiThemeProvider>
);
}
}
const theme = createMuiTheme({
palette: {
primary: blue,
secondary: purple
},
status: {
danger: "orange"
}
});
const styles = {
button: {
align: "right",
margin: 15,
marginRight: "1%"
},
button1: {
align: "right",
margin:15,
marginRight: "1%",
backgroundColor: "#21b6ae"
},
button2: {
margin: 2
}
};
export default FormUserDetails;
You probably dont require the jsx functions but please see what is the issue.
The code in short is this:
const classes = {
formControl: {
margin: this.props.theme.spacing(1),
minWidth: 120,
},
selectEmpty: {
marginTop: this.props.theme.spacing(2),
},
};
The code which I am using just to add the theme but there is an issue with props

In your code, this may point to window object, so it complains props are undefined
Have you tried
import { makeStyles } from '#material-ui/core/styles';
const useStyles = makeStyles((theme) => ({
formControl: {
margin: theme.spacing(1),
minWidth: 120,
},
selectEmpty: {
marginTop: theme.spacing(2),
},
}));
and inside your component
const classes = useStyles();

Related

unable to use MaterialUI Datepicker,Dayjs with useFormik and Yup

I am using Material UI Date picker with day js,but the issue that arising again and again is,'when I select the date on calender,1st time it updates in textfield and then it is not working.And also having problem in Yup like when touched 1st time it gives error means works perfectly but when removing the date from text field and left the field blank it does not work.'
codesandbox Link : https://codesandbox.io/s/material-ui-datepicker-error-pdvt07
code:
import "./styles.css";
import React, { useState } from "react";
import {
TextField,
Container,
Typography,
Stack,
Button,
Box
} from "#mui/material";
import { Link } from "react-router-dom";
import { Helmet } from "react-helmet-async";
import { styled } from "#mui/material/styles";
import { AdapterDayjs } from "#mui/x-date-pickers/AdapterDayjs";
import { DatePicker } from "#mui/x-date-pickers/DatePicker";
import { DesktopDatePicker } from "#mui/x-date-pickers/DesktopDatePicker";
import TodayIcon from "#mui/icons-material/Today";
import moment from "moment";
import dayjs from "dayjs";
import { LocalizationProvider } from "#mui/x-date-pickers/LocalizationProvider";
import InputAdornment from "#mui/material/InputAdornment";
import Autocomplete from "react-google-autocomplete";
import { useFormik } from "formik";
import * as Yup from "yup";
// import useResponsive from "../../hooks/useResponsive";
export default function App() {
// const navigate = useNavigate();
const validationSchema = Yup.object().shape({
firstName: Yup.string().required("First Name is required"),
lastName: Yup.string()
// .length(3, 'Last Name must be greater than 3 characters')
.required("Last Name is required"),
email: Yup.string()
.email("Invalid email")
.required("Please enter your email"),
mobile: Yup.string()
.length(10, "Mobile Number must be 10 digit")
.required("Mobile Number is required"),
dob: Yup.string().required("Dob is required"),
passingYear: Yup.string().required("Passing out year is required"),
location: Yup.string().required("Location is required"),
occupation: Yup.string().required("Occupation is required"),
address: Yup.string().required("Addres is required")
});
const formik = useFormik({
initialValues: {
firstName: "",
lastName: "",
email: "",
mobile: "",
dob: "",
passingYear: "",
location: "",
address: "",
occupation: ""
},
validationSchema,
onSubmit: (values) => {
console.log(values);
// navigate(`/verify-otp?email=${values.email}`, { replace: true });
}
});
return (
<div className="App">
<form onSubmit={formik.handleSubmit}>
<Stack direction={"column"} spacing={3}>
<Box>
<TextField
sx={{
width: "100%"
}}
id="outlined-firstName-input"
label="First Name"
name="firstName"
type={"text"}
onChange={formik.handleChange}
value={formik.values.firstName}
onBlur={formik.handleBlur}
autoComplete="off"
/>
{formik.touched.firstName && formik.errors.firstName && (
<p
style={{
color: "red",
marginTop: "5px",
marginBottom: "-15px"
}}
>
{formik.errors.firstName}
</p>
)}
</Box>
<Box>
<TextField
sx={{
width: "100%"
}}
id="outlined-lastName-input"
label="Last Name"
name="lastName"
type={"text"}
onChange={formik.handleChange}
value={formik.values.lastName}
onBlur={formik.handleBlur}
autoComplete="off"
/>
{formik.touched.lastName && formik.errors.lastName && (
<p
style={{
color: "red",
marginTop: "5px",
marginBottom: "-15px"
}}
>
{formik.errors.lastName}
</p>
)}
</Box>
<Box>
<TextField
sx={{
width: "100%"
}}
id="outlined-email-input"
label="Email address"
name="email"
type={"email"}
onChange={formik.handleChange}
value={formik.values.email}
onBlur={formik.handleBlur}
/>
{formik.touched.email && formik.errors.email && (
<p
style={{
color: "red",
marginTop: "5px",
marginBottom: "-15px"
}}
>
{formik.errors.email}
</p>
)}
</Box>
<Box>
<TextField
sx={{
width: "100%"
}}
InputProps={{
startAdornment: (
<InputAdornment position="start">+91</InputAdornment>
)
}}
id="outlined-mobile-input"
label="Mobile Number"
type="tel"
name="mobile"
onChange={formik.handleChange}
value={formik.values.mobile}
onBlur={formik.handleBlur}
autoComplete="off"
/>
{formik.touched.mobile && formik.errors.mobile && (
<p
style={{
color: "red",
marginTop: "5px",
marginBottom: "-15px"
}}
>
{formik.errors.mobile}
</p>
)}
</Box>
<Box
sx={{
width: "100%"
}}
>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<DesktopDatePicker
label="Date of birth"
inputFormat="DD/MM/YYYY"
value={dayjs(formik.values?.dob).format("DD-MM-YYYY") || ""}
onChange={(newValue) => {
formik.setFieldValue(
"dob",
dayjs(newValue).format("DD-MM-YYYY")
);
formik.setFieldTouched("dob", true);
}}
renderInput={(params) => (
<TextField
sx={{
width: "100%"
}}
{...params}
name="dob"
onBlur={formik.handleBlur}
error={formik.errors.dob && formik.touched.dob}
/>
)}
/>
</LocalizationProvider>
{formik.touched.dob && formik.errors.dob && (
<p
style={{
color: "red",
marginTop: "5px",
marginBottom: "-15px"
}}
>
{formik.errors.dob}
</p>
)}
</Box>
<Box
sx={{
width: "100%"
}}
>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<DatePicker
views={["year"]}
label="Passing year"
maxDate={dayjs().subtract(1, "year")}
value={formik.values.passingYear || ""}
onBlur={formik.handleBlur}
onChange={(newValue) => {
formik.setFieldValue("passingYear", newValue?.format("YYYY"));
}}
renderInput={(params) => (
<TextField
sx={{
width: "100%"
}}
{...params}
name="passingYear"
onBlur={formik.handleBlur}
error={
formik.errors.passingYear && formik.touched.passingYear
}
/>
)}
/>
{formik.touched.passingYear && formik.errors.passingYear && (
<p
style={{
color: "red",
marginTop: "5px",
marginBottom: "-15px"
}}
>
{formik.errors.passingYear}
</p>
)}
</LocalizationProvider>
</Box>
<Box>
<TextField
sx={{
width: "100%"
}}
id="outlined-occupation-input"
label="Occupation"
name="occupation"
type={"text"}
onChange={formik.handleChange}
value={formik.values.occupation}
onBlur={formik.handleBlur}
autoComplete="off"
/>
{formik.touched.occupation && formik.errors.occupation && (
<p
style={{
color: "red",
marginTop: "5px",
marginBottom: "-15px"
}}
>
{formik.errors.occupation}
</p>
)}
</Box>
<Box>
<Autocomplete
className="location"
style={{
width: "100%",
paddingLeft: "13px",
height: "8vh",
border: "1px solid rgb(224,224,224)",
borderRadius: "6px",
fontSize: "17px",
fontWeight: "500",
color: "#212B36",
backgroundColor: "#F9FAFB",
"&:focus": {
borderWidth: "2px",
borderColor: "darken(#2f8f1f, 5%)",
fontSize: "20px"
}
}}
apiKey={"AIzaSyABX4LTqTLQGg_b3jFOH8Z6_H5CDqn8tbc"}
onPlaceSelected={(place) => {
formik.setFieldValue("location", place?.formatted_address);
}}
types={["address"]}
componentRestrictions={{ country: "us" }}
name="location"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
/>
{formik.touched.location && formik.errors.location && (
<p
style={{
color: "red",
marginTop: "5px",
marginBottom: "-15px"
}}
>
{formik.errors.location}
</p>
)}
</Box>
<Box
sx={{
width: "100%"
}}
>
<TextField
sx={{
width: "100%"
}}
id="outlined-password-input"
label="Addres"
name="address"
value={formik.values.address}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
type="text"
multiline
rows={4}
maxRows={6}
autoComplete="off"
/>
{formik.touched.address && formik.errors.address && (
<p
style={{
color: "red",
marginTop: "5px",
marginBottom: "-15px"
}}
>
{formik.errors.address}
</p>
)}
</Box>
<Box ml={"auto"}>
<Button fullWidth size="large" type="submit" variant="contained">
Sign Up
</Button>
</Box>
</Stack>
</form>
</div>
);
}
Thanks in advance.....
you need to use dayjs format when trying to display the date. the date picker already formats the date for you in the textfield.
<DesktopDatePicker
label="Date of birth"
inputFormat="DD/MM/YYYY"
value={formik.values?.dob}
onChange={(newValue) => {
formik.setFieldValue(
"dob",
newValue
);
formik.setFieldTouched("dob", true);
}}
renderInput={(params) => (
<TextField
sx={{
width: "100%"
}}
{...params}
name="dob"
onBlur={formik.handleBlur}
error={formik.errors.dob && formik.touched.dob}
/>
)}
/>

Object is possibly "null" in event.target.files in typescript

I want to upload a csv file and later parse it in json format, I have created a state in which i am setting the file using the HTMLEvent Property.I am using typescript I have defined the possible types while defining the state but I am still getting the error.
import {
Box,
Button,
IconButton,
Modal,
Stack,
LinearProgress,
Typography
} from '#mui/material';
import React, { useState } from 'react';
import UploadIcon from '#mui/icons-material/Upload';
import CancelIcon from '#mui/icons-material/Cancel';
import { csvFileParser } from '../../../utils/csvFileParser';
type Props = {};
const BulkServiceUpload = (props: Props) => {
const [openModal, setOpenModal] = useState(false);
const [filename, setFileName] = useState<File | undefined | null>();
console.log(filename);
const style = {
position: 'absolute' as 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 600,
bgcolor: 'background.paper',
border: '2px solid #000',
boxShadow: 24,
borderRadius: '1rem',
borderWidth: 0,
p: 4
};
const serviceMasterParser = async () => {
if (filename === null) {
alert('Please select a file');
} else {
const parsedCSVData: object[] = csvFileParser(filename);
console.log(parsedCSVData);
}
};
return (
<>
<Box>
<Button
variant="contained"
color="success"
onClick={() => setOpenModal(true)}
>
<UploadIcon />
Add Service
</Button>
</Box>
<Modal open={openModal} onClose={() => setOpenModal(false)}>
<Stack padding={3} sx={style} spacing={3}>
<Typography marginY={3} variant="h5" fontWeight={600}>
Upload Service in Bulk
</Typography>
<Box
sx={{
border: 'dashed 1px black',
borderRadius: '1rem',
position: 'relative',
background: '#f0f0f0',
'&:hover': {
backgroundColor: '#EFFAF5'
}
}}
>
<Box position="absolute" width="100%" height="100%" p={3}>
<Box display="flex" justifyContent="center" alignItems="center">
<UploadIcon />
<Typography>Bulk Upload Service Master</Typography>
</Box>
<Typography fontSize="10px" textAlign="center">
only .csv file is supported
</Typography>
</Box>
<input
type="file"
accept=".csv"
onChange={(e: React.FormEvent<HTMLInputElement>) =>
setFileName((e.target as HTMLInputElement).files[0]!)
}
style={{
width: '100%',
height: '150px',
cursor: 'pointer',
opacity: '0'
}}
/>
<Box
p={1}
display={`${filename === null ? 'none' : 'flex'}`}
justifyContent="space-between"
alignItems="center"
sx={{
background: '#f5f5f5',
borderRadius: '15px'
}}
margin={2}
>
<Typography fontSize={14}>{filename?.name!}</Typography>
<IconButton
color="inherit"
aria-label="delete file"
component="label"
onClick={() => {
setFileName(undefined);
}}
>
<CancelIcon fontSize="small" />
</IconButton>
</Box>
{/* <LinearProgress variant="determinate" value={50} /> */}
</Box>
<Button
variant="contained"
color="success"
onClick={() => serviceMasterParser()}
>
<UploadIcon />
Bulk Upload
</Button>
<Button color="success" fullWidth variant="contained">
Add Single Service
</Button>
</Stack>
</Modal>
</>
);
};
export default BulkServiceUpload;
I don't want any initial value for my file.But If i will take useState value empty it will be by default an undefined value. Which is creating this problem. Please let me know how can I solve this .This is my first question so if I have made any mistake my appologies in advance.
Make sure files exists in the target
onChange={(e: React.FormEvent<HTMLInputElement>) =>
setFileName((e.target as HTMLInputElement)?.files?.[0])
}
Hi Everyone I think I have made a small typo error while setting the value of a file
<input
type="file"
accept=".csv"
onChange={(e: React.FormEvent<HTMLInputElement>) =>
setFileName((e.target as HTMLInputElement).files[0]!)
}
style={{
width: '100%',
height: '150px',
cursor: 'pointer',
opacity: '0'
}}
/>
I should have used the ! after files and it resolved the issue
<input
type="file"
accept=".csv"
onChange={(e: React.FormEvent<HTMLInputElement>) =>
setFileName((e.target as HTMLInputElement).files![0])
}
style={{
width: '100%',
height: '150px',
cursor: 'pointer',
opacity: '0'
}}
/>

How to create new components on every button click in "React"

So I want when the user clicks on the button, be able to create new CatagoryField Component that I made. When I place the component in a function and call it it will only create the component once. I will appreciate some help. I'm confused about how should I implement this?
App components
import React, { useState } from "react";
import {
Accordion,
AccordionSummary,
Chip,
Button,
IconButton,
Autocomplete,
TextField,
} from "#mui/material";
import { Grid } from "#mui/material";
import SearchBar from "material-ui-search-bar";
import DeleteIcon from "#mui/icons-material/Delete";
import ExpandMoreOutlinedIcon from "#mui/icons-material/ExpandMoreOutlined";
import AddCircleOutlineOutlinedIcon from "#mui/icons-material/AddCircleOutlineOutlined";
import HelpIcon from "#mui/icons-material/Help";
import HistoryToggleOffIcon from "#mui/icons-material/HistoryToggleOff";
import AllMembers from "./components/common/main/allMembers";
import CatagoryField from "./components/common/main/catagoryField";
const autoCompleteOptions = [
{ title: "A", year: 1994 },
{ title: "B", year: 1972 },
{ title: "C", year: 1974 },
{ title: "D", year: 2008 },
{ title: "E", year: 1957 },
{ title: "F", year: 1993 },
{ title: "G", year: 1994 },
];
const App = () => {
const [value, setValue] = useState();
const [element, setElement] = useState(0);
const doSomethingWith = () => {
return null;
};
let i = 0;
const creator = () => {
while (i < element) {
i++;
return (
<CatagoryField
catagoryName="خدماتی"
react="از آنها چیزی میخریم"
createdBy="سیستم"
disable={false}
/>
);
}
};
console.log(element);
return (
<>
<div style={{ margin: "4rem 1rem" }}>
<Accordion>
<AccordionSummary
sx={{ height: "65px" }}
aria-controls="panel1a-content"
>
<Grid
container
direction="row"
justifyContent="space-between"
alignItems="center"
>
<Grid item>
<IconButton className="chevron__icon">
<ExpandMoreOutlinedIcon />
</IconButton>
<span className="users__catagory"> دسته بندی کاربران</span>
</Grid>
<Grid item>
<IconButton>
<HistoryToggleOffIcon />
</IconButton>
<IconButton>
<HelpIcon className="help" />
</IconButton>
<span className="version">4.3.2</span>
</Grid>
</Grid>
</AccordionSummary>
<AccordionSummary
sx={{
height: "65px",
padding: "30px",
background: "#E6E6E6",
cursor: "default !important",
}}
aria-controls="panel1a-content"
>
<Grid
container
direction="row"
alignItems="center"
sx={{ display: "relative" }}
>
<Grid item>
<Button
variant="outlined"
sx={{ height: "50px" }}
size="medium"
onClick={() => setElement(element + 1)}
endIcon={
<AddCircleOutlineOutlinedIcon
sx={{ marginRight: "10px" }}
/>
}
>
افزودن دسته جدید
</Button>
</Grid>
<Grid sx={{ width: "207px" }} item>
<SearchBar
className="search__holder"
placeholder="جستجو..."
value={value}
style={{ width: "207px", height: "45px" }}
onChange={(newValue) => setValue(newValue)}
onRequestSearch={() => doSomethingWith()}
/>
</Grid>
<Grid className="sort__field" item>
<Autocomplete
sx={{
width: "207px !important",
padding: "0 !important",
backgroundColor: "white !important",
}}
options={autoCompleteOptions}
getOptionLabel={(option) => option.title}
renderTags={(value, getTagProps) =>
value.map((option, index) => (
<Chip
variant="outlined"
label={option.title}
{...getTagProps({ index })}
/>
))
}
renderInput={(params) => (
<TextField
{...params}
variant="filled"
sx={{
width: "207px !important",
padding: "0 !important",
background: "white !important",
}}
placeholder="مرتب سازی..."
/>
)}
/>
</Grid>
<Grid item>
<IconButton sx={{ margin: "0 5px" }}>
<DeleteIcon />
</IconButton>
</Grid>
<Grid item className="last__edit">
<Grid item>
<span>
آخرین ویرایش:
<a className="last_Modified" href="#">
سیستم
</a>
</span>
<span>1405/12/24 23:59 </span>
</Grid>
</Grid>
</Grid>
</AccordionSummary>
<AllMembers />
<CatagoryField
catagoryName="اپراتور سیستم"
react="اپراتور سیستم"
createdBy="سیستم"
/>
<CatagoryField
catagoryName="مشتریان"
react="به آنها چیزی فروخته ایم"
createdBy="سیستم"
/>
<CatagoryField
catagoryName="خدماتی"
react="از آنها چیزی میخریم"
createdBy="سیستم"
disable={false}
/>
{creator()}
</Accordion>
</div>
</>
);
};
export default App;
The best way in order to achieve the solution is to use a state with useMemo.and the problem with your code is that the creator acts as a function and it will only execute once try this.
import {useMemo} from 'react';
const App = () => {
const [elements , setElements] = useState(0);
const creator = useMemo(() => {
return (
<>
{Array(elements).fill(elements).map((item , index) => (
<CategoryField
key={`cat-${index}`} // key is need when mapping! it is not props
catagoryName="خدماتی"
react="از آنها چیزی میخریم"
createdBy="سیستم"
disable={false}
/>
))}
</>
)
},[elements]);//render when elements change
return (
<>
<div style={{ margin: "4rem 1rem" }}>
<Accordion>
<AccordionSummary
sx={{ height: "65px" }}
aria-controls="panel1a-content"
>
<Grid
container
direction="row"
justifyContent="space-between"
alignItems="center"
>
<Grid item>
<IconButton className="chevron__icon">
<ExpandMoreOutlinedIcon />
</IconButton>
<span className="users__catagory"> دسته بندی کاربران</span>
</Grid>
<Grid item>
<IconButton>
<HistoryToggleOffIcon />
</IconButton>
<IconButton>
<HelpIcon className="help" />
</IconButton>
<span className="version">4.3.2</span>
</Grid>
</Grid>
</AccordionSummary>
<AccordionSummary
sx={{
height: "65px",
padding: "30px",
background: "#E6E6E6",
cursor: "default !important",
}}
aria-controls="panel1a-content"
>
<Grid
container
direction="row"
alignItems="center"
sx={{ display: "relative" }}
>
<Grid item>
<Button
variant="outlined"
sx={{ height: "50px" }}
size="medium"
onClick={() => setElements(elements + 1)}
endIcon={
<AddCircleOutlineOutlinedIcon
sx={{ marginRight: "10px" }}
/>
}
>
افزودن دسته جدید
</Button>
</Grid>
<Grid sx={{ width: "207px" }} item>
<SearchBar
className="search__holder"
placeholder="جستجو..."
value={value}
style={{ width: "207px", height: "45px" }}
onChange={(newValue) => setValue(newValue)}
onRequestSearch={() => doSomethingWith()}
/>
</Grid>
<Grid className="sort__field" item>
<Autocomplete
sx={{
width: "207px !important",
padding: "0 !important",
backgroundColor: "white !important",
}}
options={autoCompleteOptions}
getOptionLabel={(option) => option.title}
renderTags={(value, getTagProps) =>
value.map((option, index) => (
<Chip
key={`chip-${index}`}
variant="outlined"
label={option.title}
{...getTagProps({ index })}
/>
))
}
renderInput={(params) => (
<TextField
{...params}
variant="filled"
sx={{
width: "207px !important",
padding: "0 !important",
background: "white !important",
}}
placeholder="مرتب سازی..."
/>
)}
/>
</Grid>
<Grid item>
<IconButton sx={{ margin: "0 5px" }}>
<DeleteIcon />
</IconButton>
</Grid>
<Grid item className="last__edit">
<Grid item>
<span>
آخرین ویرایش:
<a className="last_Modified" href="#">
سیستم
</a>
</span>
<span>1405/12/24 23:59 </span>
</Grid>
</Grid>
</Grid>
</AccordionSummary>
<AllMembers />
<CatagoryField
catagoryName="اپراتور سیستم"
react="اپراتور سیستم"
createdBy="سیستم"
/>
<CatagoryField
catagoryName="مشتریان"
react="به آنها چیزی فروخته ایم"
createdBy="سیستم"
/>
<CatagoryField
catagoryName="خدماتی"
react="از آنها چیزی میخریم"
createdBy="سیستم"
disable={false}
/>
{creator}
</Accordion>
</div>
</>
);
}
export default App;

Server Error ReferenceError: window is not defined This error happened while generating the page

I want to add Microsoft Login Button in Next Js using material Ui but
when I add package from NPM and refresh the page I got the above
error.
When I Assign ClientId="a973536f-eb3e-4fd9-9394-9f4194d69153" to Microsoft component as shown below I got the above error. How to cope with this error.
import React from "react";
import { Grid, Container, Checkbox, IconButton, FormControlLabel, TextField, Button, Link } from "#material-ui/core";
import { makeStyles } from "#material-ui/core/styles";
import Icon from "#material-ui/core/Icon";
import { loadCSS } from "fg-loadcss";
import FacebookLogin from "react-facebook-login/dist/facebook-login-render-props";
import { GoogleLogin } from "react-google-login";
import MicrosoftLogin from "react-microsoft-login";
const useStyles = makeStyles((theme) => ({
paper: {
marginTop: theme.spacing(0),
display: "flex",
flexDirection: "column",
alignItems: "center",
height: '60vh',
},
background: {
backgroundColor: "#220E1A",
borderRadius: "5px",
color: "white",import React from "react";
import { Grid, Container, Checkbox, IconButton, FormControlLabel, TextField, Button, Link } from "#material-ui/core";
import { makeStyles } from "#material-ui/core/styles";
import Icon from "#material-ui/core/Icon";
import { loadCSS } from "fg-loadcss";
import FacebookLogin from "react-facebook-login/dist/facebook-login-render-props";
import { GoogleLogin } from "react-google-login";
import MicrosoftLogin from "react-microsoft-login";
const useStyles = makeStyles((theme) => ({
paper: {
marginTop: theme.spacing(0),
display: "flex",
flexDirection: "column",
alignItems: "center",
height: '60vh',
},
background: {
backgroundColor: "#220E1A",
borderRadius: "5px",
color: "white",
},
form: {
width: "70%", // Fix IE 11 issue.
marginTop: theme.spacing(1),
},
input1: {
background: "white",
borderRadius: "25px",
color: "white",
},
submit: {
margin: theme.spacing(1, 0, 1),
borderRadius: "25px",
},
buttonGroup: {
borderRadius: "50px",
margin: theme.spacing(2, 0, 2, 0),
},
winIcon: {
padding: '0px',
margin: '0px',
width: '10px'
}
}));
export default function SignIn() {
const classes = useStyles();
//Load Fonts awesome icons
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);
};
}, []);
//google facebook,Microsoft Login response
const responseFacebook = (response) => {
console.log(response);
};
const responseGoogle = (response) => {
console.log(response);
};
const authHandler = (err, data) => {
console.log(err, data);
};
return (
<Container maxWidth="xm" className={classes.background}>
<div className={classes.paper}>
<form className={classes.form} noValidate>
<TextField
className={classes.input1}
margin="normal"
required
fullWidth
id="email"
label="Email Address"
name="email"
autoFocus
variant="filled"
/>
<TextField
className={classes.input1}
variant="filled"
margin="normal"
required
fullWidth
name="password"
label="Password"
type="password"
id="password"
autoComplete="current-password"
/>
<Grid
container
direction="column"
justify="center"
alignItems="center"
>
<Grid item >
<FormControlLabel
control={<Checkbox value="remember" color="primary" />}
label="Stay signed in"
/>
</Grid>
<Grid item>
<Button
type="submit"
medium
variant="contained"
color="primary"
className={classes.submit}
>
Sign In
</Button>
</Grid>
<Grid item>
<Link href="#" variant="body2">
Forgot password?
</Link>
</Grid>
<Grid item>
<h3 align="center">Or Via</h3>{" "}
<FacebookLogin
appId="225241158739281"
autoLoad
callback={responseFacebook}
render={(renderProps) => (
<IconButton color="primary" onClick={renderProps.onClick}>
<Icon className="fab fa-facebook" />
</IconButton>
)}
/>
<GoogleLogin
clientId="500452257814-peb71oi9612hv04svvfpvfrtch6pc5br.apps.googleusercontent.com"
render={(renderProps) => (
<IconButton
onClick={renderProps.onClick}
>
{" "}
<Icon className="fab fa-google" color="primary" />
</IconButton>
)}
buttonText="Login"
onSuccess={responseGoogle}
onFailure={responseGoogle}
cookiePolicy={"single_host_origin"}
/>
//**Problem is here IN MicrosoftLogin when i assign Id it creates the above error.**
<MicrosoftLogin
// clientId="a973536f-eb3e-4fd9-9394-9f4194d69153"
authCallback={authHandler}
redirectUri="https://localhost:3000/"
className={classes.winIcon}
children={
<IconButton>
<Icon className="fab fa-windows" color="primary" />
</IconButton>}
/>
</Grid>
</Grid>
</form>
</div>
</Container>
);
}
},
form: {
width: "70%", // Fix IE 11 issue.
marginTop: theme.spacing(1),
},
input1: {
background: "white",
borderRadius: "25px",
color: "white",
},
submit: {
margin: theme.spacing(1, 0, 1),
borderRadius: "25px",
},
buttonGroup: {
borderRadius: "50px",
margin: theme.spacing(2, 0, 2, 0),
},
winIcon: {
padding: '0px',
margin: '0px',
width: '10px'
}
}));
export default function SignIn() {
const classes = useStyles();
//Load Fonts awesome icons
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);
};
}, []);
//google facebook,Microsoft Login response
const responseFacebook = (response) => {
console.log(response);
};
const responseGoogle = (response) => {
console.log(response);
};
const authHandler = (err, data) => {
console.log(err, data);
};
return (
<Container maxWidth="xm" className={classes.background}>
<div className={classes.paper}>
<form className={classes.form} noValidate>
<TextField
className={classes.input1}
margin="normal"
required
fullWidth
id="email"
label="Email Address"
name="email"
autoFocus
variant="filled"
/>
<TextField
className={classes.input1}
variant="filled"
margin="normal"
required
fullWidth
name="password"
label="Password"
type="password"
id="password"
autoComplete="current-password"
/>
<Grid
container
direction="column"
justify="center"
alignItems="center"
>
<Grid item >
<FormControlLabel
control={<Checkbox value="remember" color="primary" />}
label="Stay signed in"
/>
</Grid>
<Grid item>
<Button
type="submit"
medium
variant="contained"
color="primary"
className={classes.submit}
>
Sign In
</Button>
</Grid>
<Grid item>
<Link href="#" variant="body2">
Forgot password?
</Link>
</Grid>
<Grid item>
<h3 align="center">Or Via</h3>{" "}
<FacebookLogin
appId="225241158739281"
autoLoad
callback={responseFacebook}
render={(renderProps) => (
<IconButton color="primary" onClick={renderProps.onClick}>
<Icon className="fab fa-facebook" />
</IconButton>
)}
/>
<GoogleLogin
clientId="500452257814-peb71oi9612hv04svvfpvfrtch6pc5br.apps.googleusercontent.com"
render={(renderProps) => (
<IconButton
onClick={renderProps.onClick}
>
{" "}
<Icon className="fab fa-google" color="primary" />
</IconButton>
)}
buttonText="Login"
onSuccess={responseGoogle}
onFailure={responseGoogle}
cookiePolicy={"single_host_origin"}
/>
//**Problem is here IN MicrosoftLogin when i assign Id it creates the above error.**
<MicrosoftLogin
// clientId="a973536f-eb3e-4fd9-9394-9f4194d69153"
authCallback={authHandler}
redirectUri="https://localhost:3000/"
className={classes.winIcon}
children={
<IconButton>
<Icon className="fab fa-windows" color="primary" />
</IconButton>}
/>
</Grid>
</Grid>
</form>
</div>
</Container>
);
}
It's related to server side rendering and client side rendering.
As Next.js provides SSR, you need to consider using objects like window, localStorage and so on. While compiling client side, those objects are fine but when Nextjs compiles server side, it shows error like you shared.
It seems like GoogleLogin uses window object if you assign the client id. You need to check that first. And lemme know the result.
Hey the easy way for Material UI Components, to rendered it on Next js framework.Just use component to render it on client side only.
(If any component use Window object on server side it will show this error)
solution:
import NoSsr from '#material-ui/core/NoSsr';
<NoSsr>
<MicrosoftLogin
clientId="a973536f-eb3e-4fd9-9394-9f4194d69153"
authCallback={authHandler}
redirectUri="https://localhost:3000/"
className={classes.winIcon}
children={
<IconButton>
<Icon className="fab fa-windows" color="primary" />
</IconButton>
}
/>
</NoSsr>

Add to cart function using react

I am building a search filter of sorts using Elasticsearch and ReactiveSearch for UI.
Each result has an ID, title, etc that I can call to display it when a user searches. I need a button for each results, and when the user clicks it, it should 'add to cart' or something like that. I just need the clicked results to be shown in the next page.
The code below is my search field, and the results that are shown. I have an onclick function, but I don't know how to proceed after that. I think I need to use redux.
class Results extends Component {
render() {
return (
<ReactiveBase
app="datataglist"
credentials="mRgWyoKGQ:f47be2a6-65d0-43b6-8aba-95dbd49eb882"
url="https://scalr.api.appbase.io"
>
<DataSearch
componentId="search"
dataField={[
"maker_tag_name",
"maker_tag_name.autosuggest",
"maker_tag_name.keyword"
]}
fieldWeights={[6, 2, 6]}
fuzziness={1}
highlightField={["maker_tag_name"]}
placeholder="Search Tag Name"
style={{
marginBottom: 20
}}
title="Maker Tag Name"
/>
<SelectedFilters />
<ReactiveList
componentId="results"
dataField="_score"
pagination={true}
react={{
and: ["system", "grouping", "unit", "search"]
}}
size={10}
noResults="No results were found..."
renderItem={renderItem}
/>
</ReactiveBase>
);
}
}
function getNestedValue(obj, path) {
const keys = path.split(".");
const currentObject = obj;
const nestedValue = keys.reduce((value, key) => {
if (value) {
return value[key];
}
return "";
}, currentObject);
if (typeof nestedValue === "object") {
return JSON.stringify(nestedValue);
}
return nestedValue;
}
function renderItem(res, triggerClickAnalytics) {
let { url, unit, title, system, score, proposed, id } = {
title: "maker_tag_name",
proposed: "proposed_standard_format",
unit: "units",
system: "system",
score: "_score",
url: "",
id: "_id"
};
title = getNestedValue(res, title);
system = getNestedValue(res, system);
url = getNestedValue(res, url);
unit = getNestedValue(res, unit);
score = getNestedValue(res, score);
proposed = getNestedValue(res, proposed);
id = getNestedValue(res, id);
return (
<Row
onClick={triggerClickAnalytics}
type="flex"
gutter={16}
key={res._id}
style={{ margin: "20px auto", borderBottom: "1px solid #ededed" }}
>
<Col style={{ width: "360px" }}>
<h3
style={{ fontWeight: "600" }}
dangerouslySetInnerHTML={{
__html: title || "Choose a valid Title Field"
}}
/>
</Col>
<div style={{ padding: "20px" }} />
<Col>
<p
style={{ fontSize: "1em", width: "300px" }}
dangerouslySetInnerHTML={{
__html: system || "Choose a valid Description Field"
}}
/>
</Col>
<div style={{ padding: "10px" }} />
<Col>
<p
style={{ fontSize: "1em" }}
dangerouslySetInnerHTML={{
__html: unit || "-"
}}
/>
</Col>
<div style={{ padding: "10px" }} />
<Col style={{ minWidth: "120px" }}>
<p
style={{ fontSize: "1em", width: "300px"}}
dangerouslySetInnerHTML={{
__html: proposed || "Choose a valid Description Field"
}}
/>
</Col>
<div style={{ padding: "10px" }} />
<Col>
<p
style={{ fontSize: "1em"}}
dangerouslySetInnerHTML={{
__html: Math.round(score) || "Choose a valid Description Field"
}}
/>
</Col>
<Col>
<Button
shape="circle"
icon={<CheckOutlined />}
style={{ marginRight: "5px" }}
onClick={()=>{this.handleClick(id)}}
/>
</Col>
<Col style={{ minWidth: "120px" }}>
<p
style={{ fontSize: "1em", width: "300px"}}
dangerouslySetInnerHTML={{
__html: id || "Choose a valid Description Field"
}}
/>
</Col>
</Row>
);
}
export default Results;
Any help would be appreciated.

Categories