ReactJS MaterialUI Modal not refreshing - javascript

i have a Modal:
with certain fields, if i open the dropdown and select one of the fields, it does change the state of the Object but doesnt render it in the UI (i reopen the dropdown with the selections so you can see whats behind):
the weird thing about it is, if i do it outside of the Modal, it does work, so it has anything todo with my Modal component?
Here is the BaseModal component:
declare interface IBaseModal {
readonly sx: BaseModalStyle;
readonly body?: React.ReactNode;
readonly isOpen: boolean;
readonly toggleModal: any;
}
const BaseModal: FC<IBaseModal> = ({sx, body, isOpen, toggleModal}: IBaseModal) => (
<Modal open={isOpen} onClose={toggleModal}>
<BaseModalView width={sx.width} height={sx.height}>
{body}
</BaseModalView>
</Modal>
)
then i use it as follows in the view component:
<BaseModal
sx={{width: 800, height: 600}}
isOpen={isModalOpen}
toggleModal={() => setModalOpen(isModalOpen)}
body={modalBody}
/>
const localizer = momentLocalizer(moment);
const [events, setEvents] = useState<CalendarEvent[]>([])
const [schedule, setSchedule] = useState<ISchedule>(initialScheduleEvent);
const [isModalOpen, setModalOpen] = useState<boolean>(false);
const [modalBody, setModalBody] = useState<React.ReactNode | undefined>();
const handleSelectDate = (e: SlotInfo) => {
setModalBody(<Grid container>
<Grid item xs={6}>
<Grid container direction="row" sx={{padding: 2}}>
<Grid item xs={12} sx={{marginBottom: 2}}>
<Typography variant="h5" align='center'>
Schedule your Post
</Typography>
</Grid>
<Grid item xs={12} sx={{marginBottom: 2}}>
<Divider/>
</Grid>
<Grid item xs={12} paddingBottom={3}>
<TextField
style={{marginBottom: 20}}
fullWidth
select
variant="outlined"
label="Plattform"
value={schedule.platform}
onChange={e => setSchedule(prevState => ({...prevState, platform: e.target.value}))}
>
{availableSocialMedias.map(item => (
<MenuItem key={item.socialMedia} value={item.socialMedia}>{item.socialMedia}</MenuItem>
))}
</TextField>
<LocalizationProvider dateAdapter={AdapterDateFns}>
<DateTimePicker
renderInput={(props) => <TextField {...props} />}
label="Schedule Date and Time"
value={schedule.schedule.start}
onChange={(e) => {
setSchedule(prevState => ({...prevState, schedule: {
...prevState.schedule, start: e!
}}))
}}
/>
</LocalizationProvider>
<TextField
fullWidth
margin="dense"
multiline
rows="5"
variant="outlined"
label="Post Content"
id="additional-info"
value={schedule.schedule.desc}
onChange={(e) => {
setSchedule(prevState => ({...prevState, schedule: {
...prevState.schedule, desc: e.target.value
}}))
}}
/>
</Grid>
<Grid item xs={12} sx={{width: '100%'}}>
<Stack spacing={2} direction="row" justifyContent='center'>
<Button variant='contained' onClick={() => createEvent()}>Post</Button>
<Button variant='contained' onClick={() => handleCloseModal()}>Close</Button>
</Stack>
</Grid>
</Grid>
</Grid>
<Grid item xs={6} sx={{backgroundColor: '#F7706EFF', justifyContent: 'center'}}>
<img style={{height: 250, width: 400}}
src={"https://web-static.wrike.com/blog/content/uploads/2020/01/Five-Features-of-a-Good-Monthly-Employee-Work-Schedule-Template.jpg?av=718acbc1e2b21264368f12b5cc57c0e2"}/>
<img style={{height: 250, width: 400}}
src={"https://imageio.forbes.com/specials-images/imageserve/605e039657de8844e59d9140/Businesswoman-Planning-Schedule-Using-Calendar-And-Laptop/0x0.jpg?format=jpg&crop=922,615,x0,y0,safe&width=960"}/>
<Typography align='center' variant='h6'>
Schedule for the whole week!
</Typography>
</Grid>
</Grid>)
setModalOpen(true);
}
It also rerenders after i select a certain value in the dropdown for example. but the Modal does not update its value, and i dont get why... i hope for any help.
Small Edit:
After selecting a value and closing / reopening the Modal, the value does change, but why not straight after selecting it but after reopening it?

I fixed the issue having the Body of the Modal, not in a variable but straight in the return body of the component

Related

Formik Warning: Maximum update depth exceeded

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

How to create a function which auto populate / fills, the text fields of a grid on a button click event. (Using react function components.)

I need to auto populate/fill below text fields when a user clicks the "Add Data" button, to do this I have to use react functional components not class components.
Please help me I'm quiet new to using React JS. Thank you.
const grid = () => {
const [data, setData] = useState(
{
Name:'',
Age:'',
Address:'',
Gender:''
)
const showResults = (e) =>{
setData(
{
Name:'John',
Age:'21',
Address:'New York',
Gender:'Male'
})}
return(
<SolutionContainer>
<DemoContainer>
<Grid>
<Grid item xs={12}>
<TextField
varient="outlined"
label="Name"
name="Name"
/>
</Grid>
<Grid>
<Grid item xs={12}>
<TextField
varient="outlined"
label="Age"
name="Age"
/>
</Grid>
<Grid>
<Grid item xs={12}>
<TextField
varient="outlined"
label="Address"
name="Address"
/>
</Grid>
<Grid>
<Grid item xs={12}>
<TextField
varient="outlined"
label="Gender"
name="Gender"
/>
</Grid>
<Grid item xs={12}>
<StyledButton
varient = "outlined"
color = "Blue"
onClick = {showResults}
>
Add Data
</StyledButton>
</Grid>
</Grid>
</DemoContainer>
</SolutionContainer>
)
}

Reactjs how to make the inputs in them work independently of each other, when you add a form button?

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.

React hook : How to call through multiple button inside a Class?

So i am using a React hook
import { useKeycloak } from '#react-keycloak/web';
import { useCallback } from 'react';
export const useAuthenticatedCallback = (callbackFn) => {
const [keycloak, initialized] = useKeycloak()
const authCallback = useCallback(() => {
// if user is not authenticated redirect to login
if (!keycloak.authenticated) {
return keycloak.login()
}
// otherwise invoke function
return callbackFn()
}, [callbackFn, initialized, keycloak])
return authCallback
}
and used in react class like a component
function AuthenticatedCallback(props) {
const authenticatedCallback = useAuthenticatedCallback(props);
return props.children(authenticatedCallback);
}
class Posts extends React.Component {
constructor() {
super()
handleTradeCallSubmit(){
if(this.state.tradeCallFormValid){
// To DO
this.setState({ ...this.state, tradeCallFormValid: false});
let _postForm = this.state.postForm;
let _companyCode = this.state.companyCode;
let requestBody = {
eventType:'create-trade-call-post',
callType:_postForm.tradeTypeId,
symbol:_companyCode,
userId: this.props.activeUser.Id,
price:_postForm.price,
stopLoss:_postForm.stopLoss,
targetPrice:_postForm.targetPrice,
targetDate:_postForm.targetDate,
tags: _companyCode,
title:_postForm.title,
notes:_postForm.notes
}
postService.create(requestBody)
.then((result) => {
NotificationManager.success(`Trade call post created successfully...`);
this.loadPosts(1);
this.clearTradeCallForm();
}).catch((error) => {
NotificationManager.error(`Trade call post creation failed..`);
console.log(`Error: ${error}`);
});
} else {
let _postForm = this.state.postForm;
_postForm.isValidationActive = true;
this.setState({ ...this.state, postForm: _postForm});
}
}
.............................
.............................
render() {
if (this.state.isLoading) {
return <CircularSpinner />;
}
return ( <AuthenticatedCallback handleTradeCallSubmit={this.handleTradeCallSubmit}>{authenticatedCallback =>
<div>
<NotificationContainer/>
<Card>
<CardContent>
<form ref={(ref) => this.formRef = ref} noValidate autoComplete="off">
<Grid className="text-center" container spacing={2}>
{
this.state.postTypes.map((postType, index) =>
<Grid key={postType.Id} item sm={6} xs={6} md={3}>
<h5>{postType.Name} <Switch key={postType.Id} checked={(postType.Name === 'TradeCall')?this.state.isTradeCallActive: !this.state.isTradeCallActive} value={postType.Id} onChange={this.handleChange} name={postType.Name} inputProps={(postType.Name === 'TradeCall') ? {'aria-label': 'secondary checkbox' }: { 'aria-label': 'primary checkbox' }} /></h5>
</Grid>
)
}
<div className={!this.state.isTradeCallActive ? 'hidden' : ''}>
<Grid container spacing={2}>
<Grid item sm={12} xs={12} md={2}>
<ButtonGroup fullWidth aria-label="small button group">
<Button onClick={()=>{this.setState({ ...this.state, tradeTypeSelected: "Sale"})}}
variant={(this.state.tradeTypeSelected === "Buy") ? "outlined" : "contained"}
color={(this.state.tradeTypeSelected === "Buy") ? "default" : "secondary"}> Sale
</Button>
<Button onClick={()=>{this.setState({ ...this.state, tradeTypeSelected: "Buy"})}}
variant={(this.state.tradeTypeSelected === "Buy") ? "contained" : "outlined"}
color={(this.state.tradeTypeSelected === "Buy") ? "secondary" : "default"}> Buy
</Button>
</ButtonGroup>
</Grid>
<Grid item sm={12} xs={12} md={2}>
<TextField fullWidth id="txtPrice" error={this.state.postForm.isValidationActive && !this.state.postForm.priceValid} name="txtPrice" type="number" InputProps={{ inputProps: { min: 0} }} size="small" label="Price" onChange={this.handleChange} variant="outlined" placeholder="Price.." />
</Grid>
<Grid item sm={12} xs={12} md={2}>
<TextField fullWidth id="txtStoploss" error={this.state.postForm.isValidationActive && !this.state.postForm.stopLossValid} name="txtStoploss" type="number" InputProps={{ inputProps: { min: 0} }} size="small" label="Stoploss" onChange={this.handleChange} variant="outlined" placeholder="SL.." />
</Grid>
<Grid item sm={12} xs={12} md={2}>
<TextField fullWidth id="txtTarget" error={this.state.postForm.isValidationActive && !this.state.postForm.targetPriceValid} name="txtTarget" type="number" InputProps={{ inputProps: { min: 0} }} size="small" label="Target price" onChange={this.handleChange} variant="outlined" placeholder="Price.." />
</Grid>
<Grid item sm={12} xs={12} md={4}>
<TextField fullWidth id="targetDate" error={this.state.postForm.isValidationActive && !this.state.postForm.targetDateValid} name="targetDate" onChange={this.handleChange} type="date" size="small" label="Target date" variant="outlined" InputLabelProps={{ shrink: true, }} />
</Grid>
</Grid>
<Grid justify="center" container spacing={2}>
<Grid item sm={12} xs={12} md={3}>
<Button size="medium" fullWidth id="btnSubmit" startIcon={<SaveIcon />} onClick={authenticatedCallback} variant="contained" color="primary"> Save </Button>
</Grid>
</Grid>
</div>
}
</AuthenticatedCallback>)
}
}
// Map redux state to props
const mapStateToProps = state => ({
activeUser: state.session.activeUser
});
// export the component.
export default connect(mapStateToProps)(Posts);
Now in button i am calling it like this
<Button size="medium" fullWidth id="btnSubmit" startIcon={<SaveIcon />} onClick={authenticatedCallback} variant="contained" color="primary"> Save </Button>
But i have a multiple button here inside this react class what will approach to call same React hook to check user login or not?
So here is one Solution I got with one of my friend
suggest in Hook Component function
function AuthenticatedCallback(props) {
const authenticatedCallback = useAuthenticatedCallback(props.handleTradeCallSubmit);
const authenticatedCallback1 = useAuthenticatedCallback(props.handleAnalysisSubmit);
return props.children(authenticatedCallback,authenticatedCallback1);
}
and changes in class level
<AuthenticatedCallback handleTradeCallSubmit={this.handleTradeCallSubmit} handleAnalysisSubmit={this.handleAnalysisSubmit}>{(authenticatedCallback,authenticatedCallback1) =>
<div>
<NotificationContainer/>
.............................
.............................
<Button size="medium" fullWidth id="btnSubmit" startIcon={<SaveIcon />} onClick={authenticatedCallback} variant="contained" color="primary"> Save </Button>
<Button fullWidth size="medium" id="btnAnalysisSubmit" startIcon={<SaveIcon />} onClick={authenticatedCallback1} variant="contained" color="primary"> Save </Button>
</div>
}
</AuthenticatedCallback>)
}
}

React: If statements inside a map function

I'm struggling with this for a while now, I'm building a page so the user can create forms dynamically I have one react component that creates the forms and one that renders it, I'm currently facing problems with editing the forms already created.
const GigApplicationRenderer = (props) => {
const {
questions,
onSelectDelete,
onSelectEdit,
classes,
theme,
handleClickOpen,
handleClose,
open
} = props;
return (
<Fragment>
{questions.map((element, index) => (
<div className={classes.li} key={element.title}>
<Grid container spacing={24}>
<Grid item xs={12}>
{element.type === 'input' ? (
<Paper index={index} className={classes.paper}>
<Title
onSelectEdit={onSelectEdit}
onSelectDelete={onSelectDelete}
element={element}
handleClose={handleClose}
open={open}
/>
<TextField
className={classes.textField}
value=""
label="answer text"
margin="normal"
/>
</Paper>
) : element.type === 'radiobox' ? (
<Paper className={classes.paper}>
<Title
onSelectEdit={onSelectEdit}
onSelectDelete={onSelectDelete}
element={element}
handleClose={handleClose}
open={open}
/>
{element.options.map(option => (
<ListItem key={option} className={classes.itemsList}>
<RadioGroup>
<FormControlLabel
label={option}
value={option}
control={<Radio color="primary" />}
/>
</RadioGroup>
</ListItem>
))}
</Paper>
) : element.type === 'checkbox' ? (
<Paper className={classes.paper}>
<Title
onSelectEdit={onSelectEdit}
onSelectDelete={onSelectDelete}
element={element}
handleClose={handleClose}
open={open}
/>
{element.options.map(option => (
<ListItem key={option} className={classes.itemsList}>
<FormControlLabel
label={option}
value={option}
control={<Checkbox checked={false} color="primary" />}
/>
</ListItem>
))}
<Divider light />
</Paper>
) : null}
</Grid>
</Grid>
</div>
))}
</Fragment>
);
};
this is the component that renders the code, it has some if statements that check the properties of the forms created and renders it accordingly.
this is the title component:
const Title = (props) => {
const {
element, onSelectDelete, onSelectEdit, index, handleClose, open
} = props;
return (
<Grid container spacing={24}>
{console.log(element.title)}
<Grid item xs={12} sm={9}>
<Typography style={{ textAlign: 'left' }} variant="subheading" gutterBottom>
{element.title}
</Typography>
</Grid>
<Grid item xs={12} sm={3}>
<Tooltip enterDelay={100} leaveDelay={100} placement="bottom" title="Edit">
<IconButton onClick={onSelectEdit(element, index)} aria-label="Edit">
<EditIcon />
</IconButton>
</Tooltip>
<Tooltip enterDelay={100} leaveDelay={100} placement="bottom" title="Delete">
<IconButton aria-label="Delete">
<DeleteIcon onClick={onSelectDelete(element)} />
</IconButton>
</Tooltip>
</Grid>
<Dialog open={open} onClose={handleClose} aria-labelledby="form-dialog-title">
<DialogTitle id="form-dialog-title">
blabla
</DialogTitle>
<DialogContent>
<DialogContentText>
To subscribe to this website, please enter your email address here. We will send updates
occasionally.
</DialogContentText>
<TextField
autoFocus
// value={element.title}
margin="dense"
label="question title"
fullWidth
/>
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="primary">
Cancel
</Button>
<Button onClick={handleClose} color="primary">
Save
</Button>
</DialogActions>
</Dialog>
</Grid>
);
};
I want it to open a dialog with the values of the element clicked so the user could edit it, the problem is that no matter which button was clicked, on the dialog, it always renders the last element of the form.
On the function onSelectEdit though, I get the correct element, I think it is happening because of the if statements of the first component.
the questions array look like this:
questions: [
{
title: 'Why do you want this job?',
type: 'input'
},
{
title: 'Do you know Javascript?',
type: 'radiobox',
options: ['yes', 'no']
},
{
title: 'What techs your know?',
type: 'checkbox',
options: ['html', 'css']
}
],
is there a way to render the correct element when the dialog opens?
I'm also open to any suggestion on how to accomplish this.

Categories

Resources