I am working on EDIT formik form, this form is in form of MODAL. when setState is passed as setState(true) than form will appear. But the problem is that without clicking onClick setState is being triggerd (according to error). In form values are already passed as it is EDIT form. I changed onClick={editStory} to onClick={()=> editStory()} still error not gone
Error: "Warning: Maximum update depth exceeded. This can happen when a
component calls setState inside useEffect, but useEffect either
doesn't have a dependency array, or one of the dependencies changes on
every render.
at EditQs (webpack-internal:///./src/new-components/Projects/EditQs.js:106:23)"
MyQs2.js
function MyQs2({row, isItemSelected, labelId, index}) {
const theme = useTheme();
const editStory = () => {
console.log('editstory is triggering')
setOpenStoryDrawer(true);
};
const [openStoryDrawer, setOpenStoryDrawer] = React.useState(false);
const handleStoryDrawerOpen = () => {
setOpenStoryDrawer(false);
};
const [allUsers, setAllUsers] = React.useState([])
const [allUsersObj, setAllUsersObj] = React.useState([])
const [allProjects, setAllProjects] = React.useState([])
//Error occur in this useEffect but i need updated data to show from firestore
React.
useEffect(() => {
readAllUsers()
readAllProjects()
}, [])
const readAllUsers = async()=> {
console.log('readAllUsesrs is calling')
try{
firebase.firestore().collection("users").where("role", "==", 'user')
.onSnapshot(function (val) {
let user = []
val.forEach(function(doc) {
user.push(doc.data().name);
setAllUsers(user)
})})
}
const readAllProjects = async() => {
console.log('readAllUsesrs is calling')
const snapshot = await firebase.firestore().collection('projects').get()
setAllProjects( snapshot.docs.map(doc => doc.data().name) );
}
return (
<>
<TableRow hover role="checkbox" aria-checked={isItemSelected} tabIndex={-1} key={index} selected={isItemSelected}>
<TableCell padding="checkbox" sx={{ pl: 3 }} onClick={(event) => handleClick(event, row.question)}>
<Checkbox
color="primary"
checked={isItemSelected}
inputProps={{
'aria-labelledby': labelId
}}
/>
</TableCell>
<TableCell
component="th"
id={labelId}
scope="row"
onClick={(event) => handleClick(event, row.projects)}
sx={{ cursor: 'pointer' }}
>
<Typography variant="subtitle1" sx={{ color: theme.palette.mode === 'dark' ? 'grey.600' : 'grey.900' }}>
{' '}
{row.question}{' '}
</Typography>
<Typography variant="caption"> {row.projects} </Typography>
</TableCell>
<TableCell>{row.projects}</TableCell>
<TableCell align="right">{row.assignTo}</TableCell>
<TableCell align="center">{row.priority}</TableCell>
<TableCell align="center">
{row.state === "published" && <Chip label="published" size="small" chipcolor="success" />}
{row.state === "unpublished" && <Chip label="unpublished" size="small" chipcolor="orange" />}
{row.state === 'Active' && <Chip label="Confirm" size="small" chipcolor="primary" />}
</TableCell>
<TableCell align="center" sx={{ pr: 3 }}>
<IconButton color="primary" size="large">
<VisibilityTwoToneIcon sx={{ fontSize: '1.3rem' }} />
</IconButton>
//below onClick is triggering
<IconButton color="secondary" size="large" onClick={()=> editStory()}
<EditTwoToneIcon sx={{ fontSize: '1.3rem' }} />
</IconButton>
</TableCell>
</TableRow>
// This calls a EditPage
<EditQs existingQs={row} open={openStoryDrawer} handleDrawerOpen={handleStoryDrawerOpen} allProjects={allProjects} allUsers={allUsers} />
</>
);
}
export default MyQs2
According to error appears in this Form page
EditQs.js
const EditQs = ({ open, handleDrawerOpen, existingQs, allProjects, allUsers }) => {
const dispatch = useDispatch();
const sendDataToFirestore = (item) => {
try{
firebase.firestore()
.collection('projects')
.doc(item.projects)
.update({
question : firebase.firestore.FieldValue.arrayUnion(item)
}).then(
dispatch(
openSnackbar({
open: true,
message: 'New Question added',
variant: 'alert',
alert: {
color: 'success'
},
close: false
})
)
)
}catch(err){
console.log('an error occured', err)
}
}
const formik = useFormik({
enableReinitialize: true, //if i remove this, error gone but this is responsible
for adding values in formik during render
validateOnChange:false,
validateOnBlur:false,
initialValues: {
id: existingQs.id ? existingQs.id : '',
question: existingQs.question? existingQs.question : '',
projects: existingQs.projects? existingQs.projects : '',
assignTo: existingQs.assignTo ? existingQs.assignTo : '',
priority: existingQs.priority ? existingQs.priority : '',
dueDate: existingQs.dueDate ? new Date(existingQs.dueDate) : new Date(),
state: existingQs.state ? existingQs.state : '',
image: existingQs.image
},
validationSchema,
onSubmit: (values,{resetForm}) => {
const item = {
id: values.id,
question: values.question,
projects: values.projects,
assignTo: values.assignTo,
priority: values.priority,
dueDate: values.dueDate ? new Date(values.dueDate) : new Date(),
state: values.state,
image: values.image
};
sendDataToFirestore(item);
() => handleDrawerOpen();
resetForm()
readAllProjects()
}
});
return (
<Drawer
sx={{
ml: open ? 3 : 0,
flexShrink: 0,
zIndex: 1200,
overflowX: 'hidden',
width: { xs: 320, md: 450 },
'& .MuiDrawer-paper': {
height: '100vh',
width: { xs: 320, md: 450 },
position: 'fixed',
border: 'none',
borderRadius: '0px'
}
}}
variant="temporary"
anchor="right"
open={open}
ModalProps={{ keepMounted: true }}
onClose={() => handleDrawerOpen}
>
{open && (
<Box sx={{ p: 3 }}>
<form onSubmit={formik.handleSubmit}>
<LocalizationProvider dateAdapter={AdapterDateFns}>
<Grid container spacing={3}>
<Grid item xs={12}>
<Typography variant="h4">Edit Question</Typography>
</Grid>
<Grid item xs={12}>
<Grid container alignItems="center" spacing={2}>
<Grid item xs={12} sm={4}>
<Typography variant="subtitle1">Question:</Typography>
</Grid>
<Grid item xs={12} sm={8}>
<TextField
fullWidth
id="question"
name="question"
multiline
rows={3}
value={formik.values.question}
onChange={formik.handleChange}
error={formik.touched.question && Boolean(formik.errors.question)}
helperText={formik.touched.question && formik.errors.question}
/>
</Grid>
</Grid>
</Grid>
<Grid item xs={12}>
<Grid container alignItems="center" spacing={2}>
<Grid item xs={12} sm={4}>
<Typography variant="subtitle1">Assign to:</Typography>
</Grid>
<Grid item xs={12} sm={8}>
<FormControl fullWidth sx={{ m: 1 }}>
<InputLabel>Choose a user</InputLabel>
<Select
id="assignTo"
name="assignTo"
displayEmpty
value={formik.values.assignTo}
onChange={formik.handleChange}
label='Assign to'
inputProps={{ 'aria-label': 'assignTo' }}
>
{allUsers.map((val, index) => (
<MenuItem key={index} value={val}>
{val}
</MenuItem>
))}
</Select>
</FormControl>
</Grid>
</Grid>
</Grid>
<Grid item xs={12}>
<Grid container alignItems="center" spacing={2}>
<Grid item xs={12} sm={4}>
<Typography variant="subtitle1">project:</Typography>
</Grid>
<Grid item xs={12} sm={8}>
<FormControl fullWidth sx={{ m: 1 }}>
<InputLabel>Choose a Project</InputLabel>
<Select
id="projects"
name="projects"
displayEmpty
value={formik.values.projects}
onChange={formik.handleChange}
label='projects'
inputProps={{ 'aria-label': 'projects' }}
>
{allProjects.map((val, index) => (
<MenuItem key={index} value={val}>
{val}
</MenuItem>
))}
</Select>
</FormControl>
</Grid>
</Grid>
</Grid>
<Grid item xs={12}>
<Grid container alignItems="center" spacing={2}>
<Grid item xs={12} sm={4}>
<Typography variant="subtitle1">Prioritize:</Typography>
</Grid>
<Grid item xs={12} sm={8}>
<FormControl>
<RadioGroup
row
aria-label="color"
value={formik.values.priority}
onChange={formik.handleChange}
name="priority"
id="priority"
>
<FormControlLabel value="low" control={<Radio color="primary" sx={{ color: 'primary.main' }} />} label="Low" />
<FormControlLabel
value="medium"
control={<Radio color="warning" sx={{ color: 'warning.main' }} />}
label="Medium"
/>
<FormControlLabel value="high" control={<Radio color="error" sx={{ color: 'error.main' }} />} label="High" />
</RadioGroup>
</FormControl>
</Grid>
</Grid>
</Grid>
<Grid item xs={12}>
<Grid container alignItems="center" spacing={2}>
<Grid item xs={12} sm={4}>
<Typography variant="subtitle1">State:</Typography>
</Grid>
<Grid item xs={12} sm={8}>
<FormControl fullWidth sx={{ m: 1 }}>
<InputLabel >State of question</InputLabel>
<Select
id="state"
name="state"
displayEmpty
value={formik.values.state}
onChange={formik.handleChange}
// label='choose question state'
inputProps={{ 'aria-label': 'choose question state' }}
>
{states.map((val, index) => (
<MenuItem key={index} value={val.title}>
{val.title}
</MenuItem>
))}
</Select>
</FormControl>
</Grid>
</Grid>
</Grid>
<Grid item xs={12}>
<AnimateButton>
<Button fullWidth variant="contained" type="submit">
Save
</Button>
</AnimateButton>
</Grid>
</Grid>
</LocalizationProvider>
</form>
</Box>
)}
</Drawer>
);
};
export default EditQs;
First issue is setAllUsers(readAllUsers()). You are calling setAllUsers passing a function readAllUsers as argument but inside this function you are calling setAllUsers again
.onSnapshot(function (val) {
let user = []
val.forEach(function(doc) {
user.push(doc.data().name);
// setAllUsers again
setAllUsers(user)
})})
Every time you change the state, your component is getting rerendered.
It would be better to write different useEffect for each state setup. Each useEffect will have different dependentcies. Setting correct depencencies needs analysing the code. Otherwise you might not get correct state or your component might keep rerendering
I hope your day is going well. I am a new user of material UI and I am working on building my first profile page (image below).
As I am getting closer to building this page, I am struggling to create a grid system that allows the about section to be directly under the three panels (see image below).
How do I remove the padding between the about section and three pannels (code below)?
return (
<>
<Helmet>
<title>Dashboard: Project Details | Material Kit Pro</title>
</Helmet>
<Box
sx={{
backgroundColor: 'background.default',
minHeight: '100%',
py: 8
}}
>
<Container >
<AppBar></AppBar>
<Grid container spacing={1}>
<Grid item xs={12} md={3}>
<Box
style={{ height: '100%', width: '100%'}}
>
<WritersSidePanel />
</Box>
</Grid>
<Grid item xs={12} md={9}>
<WritersPageTopPanel />
</Grid>
<Box style={{ marginDown: '90%'}}>
<Grid item xs={12} container
direction="column"
alignItems="flex-end"
justify="flex-end">
<Box
style={{ width: '75%', height: '100%'}}
>
<AboutSection description={description} />
</Box>
</Grid>
<Grid item xs={12} container
direction="column"
alignItems="flex-end"
justify="flex-end">
<Box
style={{ width: '75%'}}
>
<SampleStory description={description} />
</Box>
</Grid>
</Box>
</Grid>
</Container>
</Box>
</>
);
};
How can I make the state in the added forms work independently of changes in other similar forms?
Forms are added through locationAdd
const LocationBody = ({filteredServersData, locationAdd,
deleteLocationCell, handleChangeFilter,
filters, locationsData, envsData }) => {
const classes = useStyles();
const locationsSelect = locationsData.map((item) => {
return <MenuItem key={item.locationID} value={item.locationID}>{item.name}</MenuItem>;
})
const envsSelect = envsData.map((item, index) => {
return <MenuItem key={index} value={item.envID}>{item.name}</MenuItem>;
})
const serversSelect = filteredServersData.map(item => <Typography variant="h6" component="h1">
{item.name}
</Typography>)
return (
<div>
{locationAdd.map(i => <Container className={classes.root} key={i.id}>
<Grid container spacing={3} className="arr">
<Grid item xs={12}>
<Box display="flex" justifyContent="space-between">
<Typography variant="h5" component="h1">
Тестовая локация {i.id}
</Typography>
<IconButton
aria-label="delete" color="secondary"
className={classes.margin}
onClick={() => deleteLocationCell(i)}>
<DeleteIcon fontSize="medium" />
</IconButton>
</Box>
</Grid>
<Grid item xs={12} className={classes.filtersContainer}>
<Box display="flex" justifyContent="space-between">
<Box display="flex" className={classes.fieldsContainer}>
<Typography variant="h6" component="h1">
Локация
</Typography>
<FormControl variant="outlined">
<Select
value={filters.locationID}
onChange={handleChangeFilter}
label="LocationID"
labelId="locationID"
name="locationID"
>
{locationsSelect}
</Select>
</FormControl>
<FormControl variant="outlined">
<Select
value={filters.envID}
onChange={handleChangeFilter}
label="EnvID"
labelId="envID"
name="envID" >
{envsSelect}
</Select>
</FormControl>
{serversSelect}
</Box>
</Box>
</Grid>
</Grid>
</Container>)}
</div>
)
}
You can create a new component for added forms and each component will handle its own state only, without sharing it with other siblings.
Or, if you don't want to create a new component, and want to keep the current code as it is, you may differentiate each form's state by prefixing it with the form's unique ID.
Suppose we have the Grid
const App = () => {
const useStyles = makeStyles(theme => ({
root: {
flexGrow: 1
},
paper: {
padding: theme.spacing(2),
textAlign: "center",
color: theme.palette.text.secondary
}
}));
const classes = useStyles();
return (
<>
<Grid container>
<Grid item xs={8}>
<Grid container spacing={3}>
<Grid item xs={12}>
<Paper className={classes.paper}>xs=12</Paper>
</Grid>
<Grid item xs={12} sm={6}>
<Paper className={classes.paper}>xs=12 sm=6</Paper>
</Grid>
<Grid item xs={12} sm={6}>
<Paper className={classes.paper}>xs=12 sm=6</Paper>
</Grid>
<Grid item xs={6} sm={3}>
<Paper className={classes.paper}>xs=6 sm=3</Paper>
</Grid>
<Grid item xs={6} sm={3}>
<Paper className={classes.paper}>xs=6 sm=3</Paper>
</Grid>
<Grid item xs={6} sm={3}>
<Paper className={classes.paper}>xs=6 sm=3</Paper>
</Grid>
<Grid item xs={6} sm={3}>
<Paper className={classes.paper}>xs=6 sm=3</Paper>
</Grid>
</Grid>
</Grid>
<Grid item xs={4}>
<Grid item xs={12}>
</Grid>
</Grid>
</Grid>
</>
);
};
export default App;
How can we imitate PaddingTop and add empty rows from the top using Grid ?
You can acquire the space using spacing={10} in the top Grid container to adjust.
Also, you can add a new Grid with xs={12} if you want something to show.
import React from "react";
import "./styles.css";
import { Grid, makeStyles, Paper } from "#material-ui/core";
export default (App = () => {
const useStyles = makeStyles(theme => ({
root: {
flexGrow: 1
},
paper: {
padding: theme.spacing(2),
textAlign: "center",
color: theme.palette.text.secondary
}
}));
const classes = useStyles();
return (
<>
<Grid container spacing={2}>
<Grid item xs={12}>
<Paper className={classes.paper}>xs=12</Paper>
</Grid>
<Grid item xs={8}>
<Grid container spacing={3}>
<Grid item xs={12}>
<Paper className={classes.paper}>xs=12</Paper>
</Grid>
<Grid item xs={12} sm={6}>
<Paper className={classes.paper}>xs=12 sm=6</Paper>
</Grid>
<Grid item xs={12} sm={6}>
<Paper className={classes.paper}>xs=12 sm=6</Paper>
</Grid>
<Grid item xs={6} sm={3}>
<Paper className={classes.paper}>xs=6 sm=3</Paper>
</Grid>
<Grid item xs={6} sm={3}>
<Paper className={classes.paper}>xs=6 sm=3</Paper>
</Grid>
<Grid item xs={6} sm={3}>
<Paper className={classes.paper}>xs=6 sm=3</Paper>
</Grid>
<Grid item xs={6} sm={3}>
<Paper className={classes.paper}>xs=6 sm=3</Paper>
</Grid>
</Grid>
</Grid>
<Grid item xs={4}>
<Grid item xs={12} />
</Grid>
</Grid>
</>
);
});
Hello i need to move my grids to display the following layout
However right now my layout looks like this
I am still trying to understand how grid work, below is my attempt at formatting the grid, however it doesn't want to align itself in the manor of which i wish
<Grid item xs={8}>
<Grid className = {classes.root} container direction ="column"
alignItems="flex-start">
{/* <Typography variant="title" style={{ }}>example</Typography> */}
<Paper className = {classes.mainDetailsPaper}>
<Typography variant="title">Main Details</Typography><Divider />
<Typography variant="subheading">Organisation: </Typography>
<Typography variant="subheading">Category: </Typography>
<Typography variant="subheading">Sub Category: </Typography>
</Paper>
</Grid>
<Grid className = {classes.root} container direction ="row"
alignItems="flex-end">
<Paper className = {classes.subDetailsPaper}>
<Typography variant="title">Contract Dates</Typography><Divider />
<Typography variant="subheading">Start Date: </Typography>
</Paper>
<Paper className = {classes.subDetailsPaper}>
<Typography variant="title">Valuation</Typography><Divider />
<Typography variant="subheading">Estimated Contract Value: </Typography>
</Paper>
<Paper className = {classes.subDetailsPaper}>
<Typography variant="title">Supplier Info</Typography><Divider />
</Paper>
</Grid>
</Grid>