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

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>)
}
}

Related

ReactJS MaterialUI Modal not refreshing

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

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>
)
}

Error when passing a functional component to a class component as a component prop

I create a functional component and a class component.
In the render method I want to call my functional component as a component prop.
My code:
function projectList(props) {
const { classes } = props
return (
<div>
{projects.slice(0, 5).map(project => (
<Card className={classes.card} key={project.id}>
<CardHeader
classes={{ title: classes.h6, subheader:
classes.subtitle1 }}
title={project.projectName}
subheader={project.h5}
/>
<CardActionArea>
<CardMedia
component="img"
alt={project.h5}
className={classes.media}
image={project.img}
/>
<CardContent>
<Typography paragraph>
{project.paragraph}
</Typography>
</CardContent>
</CardActionArea>
<CardActions className={props.classes.actions}>
<Button
className={props.classes.projectButton}
component={Link}
to={project.pathname}
size="medium"
color="secondary"
>
Project Details
</Button>
</CardActions>
</Card>
))}
</div>
)
}
projectList.propTypes = {
classes: PropTypes.any.isRequired, // eslint-disable-line
}
class Projects extends Component {
static propTypes = {
classes: PropTypes.any.isRequired, // eslint-disable-line
}
render() {
const { classes } = this.props
return (
<Grid container className={classes.projectPage}
direction="row">
<Grid item xs />
<Grid item>
<Grid container alignItems="center" direction="column">
{/* Title */}
<Grid item>
<Typography className={classes.h5} variant="h5">Latest
Projects</Typography>
</Grid>
<Grid item xs={12} sm={6} component={projectList} />
<Grid item className={classes.nextButton}>
<Button
className={classes.contained}
size="medium"
variant="contained"
onClick={this.handleShowMore}
>
See More
</Button>
</Grid>
</Grid>
</Grid>
<Grid item xs />
</Grid>
)
}
}
export default withStyles(styles)(Projects)
I have this error message appearing
index.js:1452 Warning: Failed prop type: The prop classes is marked as required in projectList, but its value is undefined.
Anyone could help me fix this ?
Not sure where that <Grid/> component comes from but you could pass an inline wrapper for projectLists and return it as a jsx element (you would need a capital first letter though):
<Grid item xs={12} sm={6} component={() => <ProjectList classes={classes} />} />
Don't forget to change the decleration to capital letter:
function ProjectList(props) {
...

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