how to show data fetched from api in select mui - javascript

I'm trying to show the data, I fetched from Api in select menu. but there seems to be a issue. I'm getting the data, but it's not showing in the select menu. it just shows empty. but I can get the mapped data in console. it just not showing in the select component.
help me figure out. thanks in advance :)
here's my code
export function TransferRBTCard(props) {
const [TransferData, setTransferData] = useState([])
const [ContactValue, setContactValue] = useState('')
const handleChange = (event) => {
setContactValue(event.target.value);
};
const TokenData = () => {
axios.get('http://localhost:8006/api/v2/get/list').then(function (res) {
try {
var result = res.data.data;
console.log(result)
setTransferData(result)
}
catch (error) {
console.log(error)
}
})
}
useEffect(() => {
TokenData()
}, [])]
const handleSubmit = (evnt,) => {
evnt.preventDefault();
axios.post('http://localhost:8006/api/v2/add/transfer')
.then(response => {
if (response.data.success === true) {
alert(response.data.message)
}
})
.catch(error => {
console.log(error.message)
});
}
return (
<Card {...props}>
<CardContent>
<Stack direction="row" alignItems="center" gap={1}>
<ShareOutlinedIcon sx={{ color: "text.secondary" }} />
<Typography sx={{ fontSize: 16, fontWeight: 'bold' }} color="text.secondary" gutterBottom>
Transfer RBT
</Typography>
</Stack>
<Grid>
<FormControl size="small" fullWidth >
<Stack flexDirection='column' gap={1.5} mt={1}>
<InputLabel id="Contact Select" sx={{ mt: 1 }}>Select Contact</InputLabel>
<Select
labelId="Contact Select"
id="demo-simple-select"
value={ContactValue}
label='Select Contact'
onChange={handleChange}
>
{TransferData.map((data) => {
<MenuItem key={data.id} value={data.id}>{data.name}</MenuItem>
})}
</Select>
<TextField
id="filled-hidden-label-small"
label="Receiver" variant="outlined" size="small"
onChange={handleChange}
value={TransferData}
name="Receiver"
inputProps={
{ readOnly: true, }}
className="form-control"
/>
<TextField
id="filled-hidden-label-small" type='number'
label="Amount" variant="outlined" size="small"
onChange={handleChange}
name="Amount"
className="form-control"
/>
<TextField
id="filled-hidden-label-small"
label="Comments" variant="outlined"
multiline
rows={2}
onChange={handleChange}
name="Comments"
className="form-control"
/>
<Button
variant="contained"
type="submit"
onClick={handleSubmit}
sx={{ alignSelf: 'center', backgroundColor: '#000073' }} >Submit</Button>
</Stack>
</FormControl>
</Grid>
</CardContent>
</Card>
);
}

You are not returning from the map function (more correctly, you return undefined by not stating a return).
Change this:
{TransferData.map((data) => {
<MenuItem key={data.id} value={data.id}>{data.name}</MenuItem>
})}
to this:
{TransferData.map((data) => (
<MenuItem key={data.id} value={data.id}>{data.name}</MenuItem>
))}
Note that it is the same as writing:
{TransferData.map((data) => {
return <MenuItem key={data.id} value={data.id}>{data.name}</MenuItem>
})}

Related

I want Link component from router dom to work only when validation is correct

I want if is possible the Link component from react-router-dom to not work until validations are made correct. If I remove the link, validation works as I want.
I saw something with ifValidate but I don't understand exactly how to apply it.
import { Link } from "react-router-dom";
const AgentProfile = () => {
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");
const [phone, setPhone] = useState("");
const [proficiency, setProficiency] = useState("");
const [address, setAddress] = useState("");
const [city, setCity] = useState("");
const [firstNameError, setFirstNameError] = useState(false);
const [lastNameError, setLastNameError] = useState(false);
const [phoneError, setPhoneError] = useState(false);
const [proficiencyError, setProficiencyError] = useState(false);
const [addressError, setAddressError] = useState(false);
const [cityError, setCityError] = useState(false);
const handleSubmit = (e) => {
e.preventDefault();
setFirstNameError(false);
setLastNameError(false);
setPhoneError(false);
setProficiencyError(false);
setAddressError(false);
setCityError(false);
if (firstName === "") {
setFirstNameError(true);
}
if (lastName === "") {
setLastNameError(true);
}
if (phone === "") {
setPhoneError(true);
}
if (proficiency === "") {
setProficiencyError(true);
}
if (address === "") {
setAddressError(true);
}
if (city === "") {
setCityError(true);
}
if (firstName && lastName && phone && proficiency && address && city) {
console.log(firstName, lastName, phone, proficiency, address, city);
}
};
return (
<>
<Box sx={{ display: "flex", flexDirection: "column", width: "65%" }}>
<Box ml={10} pt={6}>
<Typography variant="h3" color="GrayText">
Hello! Please tell us a little bit about yourself.
</Typography>
</Box>
<form noValidate autoComplete="off" onSubmit={handleSubmit}>
<Box sx={{ display: "flex" }} ml={10} mt={2}>
<Box sx={{ width: "50%" }}>
{/* <Typography variant="body2">First Name</Typography> */}
<TextField
onChange={(e) => setFirstName(e.target.value)}
label="First Name"
type="text"
required
variant="outlined"
size="small"
error={firstNameError}
/>
</Box>
<Box>
{/* <Typography variant="body2">Last Name</Typography> */}
<TextField
onChange={(e) => setLastName(e.target.value)}
label="Last Name"
type="text"
required
variant="outlined"
size="small"
error={lastNameError}
/>
</Box>
</Box>
<Box sx={{ display: "flex" }} ml={10} mt={4}>
<Box sx={{ width: "50%" }}>
{/* <Typography variant="body2">Phone</Typography> */}
<TextField
onChange={(e) => setPhone(e.target.value)}
label="Phone"
type="text"
required
variant="outlined"
size="small"
error={phoneError}
/>
</Box>
<Box sx={{ width: "30%" }}>
{/* <Typography variant="body2">Work Proficiency</Typography> */}
<FormControl fullWidth size="small" required>
<InputLabel id="demo-simple-select-label">
Work Proficiency
</InputLabel>
<Select
onChange={(e) => setProficiency(e.target.value)}
labelId="demo-simple-select-label"
id="demo-simple-select"
value={proficiency}
label="Work Proficiency"
error={proficiencyError}
>
<MenuItem value={2}>Two years</MenuItem>
<MenuItem value={5}>Five years</MenuItem>
<MenuItem value={10}>Ten years</MenuItem>
</Select>
</FormControl>
</Box>
</Box>
<Box ml={10} mt={6}>
{/* <Typography variant="body2">Street Address</Typography> */}
<TextField
onChange={(e) => setAddress(e.target.value)}
label="Street Address"
type="text"
required
variant="outlined"
size="small"
sx={{ width: "80%" }}
error={addressError}
/>
</Box>
<Box ml={10} mt={6}>
{/* <Typography variant="body2">City</Typography> */}
<TextField
onChange={(e) => setCity(e.target.value)}
label="City"
type="text"
required
variant="outlined"
size="small"
sx={{ width: "40%" }}
error={cityError}
/>
</Box>
<Box mt={8} sx={{ display: "flex", justifyContent: "space-between" }}>
<Box ml={8}>
<Button variant="outlined" sx={{ borderRadius: "20px" }}>
Back
</Button>
</Box>
<Box mr={18}>
<Button
type="submit"
variant="contained"
sx={{ borderRadius: "20px" }}
>
<Link to="/experienceconfirm">Next</Link>
</Button>
</Box>
</Box>
</form>
</Box>
</>
);
};
export default AgentProfile;
Something like if validation is not correct link component to be disabled, and when user completes every field to become active.
You can prevent the default link action when the link is clicked and add an imperative navigation action in the form's submit handler when validation is passed. Additionally you can disable the button while any state is still falsey.
Example:
import { Link, useNavigate } from 'react-router-dom';
const AgentProfile = () => {
const navigate = useNavigate();
...
const handleSubmit = (e) => {
e.preventDefault();
setFirstNameError(false);
setLastNameError(false);
setPhoneError(false);
setProficiencyError(false);
setAddressError(false);
setCityError(false);
let isError = false;
if (!firstName) {
setFirstNameError(true);
isError = true;
}
if (!lastName) {
setLastNameError(true);
isError = true;
}
if (!phone) {
setPhoneError(true);
isError = true;
}
if (!proficiency) {
setProficiencyError(true);
isError = true;
}
if (!address) {
setAddressError(true);
isError = true;
}
if (!city) {
setCityError(true);
isError = true;
}
if (!isError) {
navigate("/experienceconfirm"); // <-- navigate on no error
}
};
return (
<>
<Box sx={{ display: "flex", flexDirection: "column", width: "65%" }}>
...
<form noValidate autoComplete="off" onSubmit={handleSubmit}>
...
<Box mt={8} sx={{ display: "flex", justifyContent: "space-between" }}>
<Box ml={8}>
<Button variant="outlined" sx={{ borderRadius: "20px" }}>
Back
</Button>
</Box>
<Box mr={18}>
<Button
type="submit"
variant="contained"
sx={{ borderRadius: "20px" }}
disabled={!(firstName && lastName && phone && proficiency && address && city)}
>
<Link
to="/experienceconfirm"
onClick={e => e.preventDefault()} // <-- prevent immediate navigation
>
Next
</Link>
</Button>
</Box>
</Box>
</form>
</Box>
</>
);
};
import { useEffect, useMemo } from "react";
import { Link } from "react-router-dom";
const AgentProfile = () => {
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");
const [phone, setPhone] = useState("");
const [proficiency, setProficiency] = useState("");
const [address, setAddress] = useState("");
const [city, setCity] = useState("");
const [firstNameError, setFirstNameError] = useState(false);
const [lastNameError, setLastNameError] = useState(false);
const [phoneError, setPhoneError] = useState(false);
const [proficiencyError, setProficiencyError] = useState(false);
const [addressError, setAddressError] = useState(false);
const [cityError, setCityError] = useState(false);
useEffect(() => {
if (firstName === "") {
setFirstNameError(true);
}
if (lastName === "") {
setLastNameError(true);
}
if (phone === "") {
setPhoneError(true);
}
if (proficiency === "") {
setProficiencyError(true);
}
if (address === "") {
setAddressError(true);
}
if (city === "") {
setCityError(true);
}
}, [firstName, lastName, phone, proficiency, address, city])
const hasError = useMemo(
() => firstNameError || lastNameError || phoneError || proficiencyError || addressError || cityError
, [firstNameError, lastNameError, phoneError, proficiencyError, addressError, cityError]
)
return (
<>
<Box sx={{ display: "flex", flexDirection: "column", width: "65%" }}>
<Box ml={10} pt={6}>
<Typography variant="h3" color="GrayText">
Hello! Please tell us a little bit about yourself.
</Typography>
</Box>
<form noValidate autoComplete="off" onSubmit={handleSubmit}>
<Box sx={{ display: "flex" }} ml={10} mt={2}>
<Box sx={{ width: "50%" }}>
{/* <Typography variant="body2">First Name</Typography> */}
<TextField
onChange={(e) => setFirstName(e.target.value)}
label="First Name"
type="text"
required
variant="outlined"
size="small"
error={firstNameError}
/>
</Box>
<Box>
{/* <Typography variant="body2">Last Name</Typography> */}
<TextField
onChange={(e) => setLastName(e.target.value)}
label="Last Name"
type="text"
required
variant="outlined"
size="small"
error={lastNameError}
/>
</Box>
</Box>
<Box sx={{ display: "flex" }} ml={10} mt={4}>
<Box sx={{ width: "50%" }}>
{/* <Typography variant="body2">Phone</Typography> */}
<TextField
onChange={(e) => setPhone(e.target.value)}
label="Phone"
type="text"
required
variant="outlined"
size="small"
error={phoneError}
/>
</Box>
<Box sx={{ width: "30%" }}>
{/* <Typography variant="body2">Work Proficiency</Typography> */}
<FormControl fullWidth size="small" required>
<InputLabel id="demo-simple-select-label">
Work Proficiency
</InputLabel>
<Select
onChange={(e) => setProficiency(e.target.value)}
labelId="demo-simple-select-label"
id="demo-simple-select"
value={proficiency}
label="Work Proficiency"
error={proficiencyError}
>
<MenuItem value={2}>Two years</MenuItem>
<MenuItem value={5}>Five years</MenuItem>
<MenuItem value={10}>Ten years</MenuItem>
</Select>
</FormControl>
</Box>
</Box>
<Box ml={10} mt={6}>
{/* <Typography variant="body2">Street Address</Typography> */}
<TextField
onChange={(e) => setAddress(e.target.value)}
label="Street Address"
type="text"
required
variant="outlined"
size="small"
sx={{ width: "80%" }}
error={addressError}
/>
</Box>
<Box ml={10} mt={6}>
{/* <Typography variant="body2">City</Typography> */}
<TextField
onChange={(e) => setCity(e.target.value)}
label="City"
type="text"
required
variant="outlined"
size="small"
sx={{ width: "40%" }}
error={cityError}
/>
</Box>
<Box mt={8} sx={{ display: "flex", justifyContent: "space-between" }}>
<Box ml={8}>
<Button variant="outlined" sx={{ borderRadius: "20px" }}>
Back
</Button>
</Box>
<Box mr={18}>
<Button
type="submit"
variant="contained"
sx={{ borderRadius: "20px" }}
>
{hasError? "Next" : <Link to="/experienceconfirm">Next</Link>}
</Button>
</Box>
</Box>
</form>
</Box>
</>
);
};
export default AgentProfile;
I added useEffect to define whether the user inputted all fields or not.
If there is an error, the button only shows the string and has no action.

React+Material UI: How to change the font size of the Select component?

I'm developing a web app using React + Material UI. I would like to change the font size of the Select component. I'm having to use the MenuProps property, as the code snippet that follows. However, it's not working.
const MenuProps = {
PaperProps: {
sx: {
'& .MuiMenuItem-root': {
fontSize: 10,
},
},
style: {
fontSize: 10,
},
},
};
const MultipleSelectTags = () => {
const [tagFilter, setTagFilter] = useState([]);
const handleChange = (event) => {
const {
target: { value },
} = event;
setTagFilter(
typeof value === 'string' ? value.split(',') : value,
);
};
return (
<div>
<FormControl sx={{ m: 1, width: 200 }} size="small">
<InputLabel>Tag</InputLabel>
<Select
multiple
value={tagFilter}
onChange={handleChange}
input={<OutlinedInput label="Tag" />}
renderValue={(selected) => selected.join(', ')}
MenuProps={MenuProps}
>
{names.map((name) => (
<MenuItem key={name} value={name}>
<Checkbox checked={tagFilter.indexOf(name) > -1} />
<ListItemText primary={name} />
</MenuItem>
))}
</Select>
</FormControl>
</div>
);
}
Can somebody help me?
You can just add the font size prop directly to the Input:
<Select
multiple
value={tagFilter}
onChange={handleChange}
input={<OutlinedInput sx={{fontSize: '2rem'}} label="Tag" />}
renderValue={(selected) => selected.join(', ')}
>
{names.map((name) => (
<MenuItem key={name} value={name}>
<Checkbox checked={tagFilter.indexOf(name) > -1} />
<ListItemText primary={name} />
</MenuItem>
))}
</Select>
Here is a solution:
<Select
multiple
value={tagFilter}
onChange={handleChange}
input={<OutlinedInput label="Tag" />}
renderValue={(selected) => selected.join(', ')}
id="my-simple-select"
sx={{
'& #my-simple-select': {
fontSize: '2rem',
}
}}
>
{names.map((name) => (
<MenuItem key={name} value={name}>
<Checkbox checked={tagFilter.indexOf(name) > -1} />
<ListItemText primary={name} />
</MenuItem>
))}
</Select>
Also, if you want to apply it on the class level: '& .MuiSelect-select'
This is how I did it
<Select fullWidth
labelId="stateIdlabel"
id="stateId"
name="stateId" value={values.stateId}
label="label"
sx={{fontSize:'large'}}>
<MenuItem sx={{fontSize:'large'}} value={1}>OK</MenuItem>
<MenuItem sx={{fontSize:'large'}} value={2}>NOT</MenuItem>
</Select>

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

Get value from few Select in Material-UI

I have two MUI Select components on my page. I'm trying to set values depends on id of Select. I've checked (id === "breed-select") in console and (at first) it's true, but immediately after that it become false, and i cant understand why. Where i made a mistake? May be there is a better way to set values of two Select components? CodeSandbox
import React from 'react';
import './AddCatPopup.css';
import {Box, Button, FormControl, InputLabel, MenuItem, Select, TextField} from '#mui/material';
import {theme} from '../../theme';
import {ThemeProvider} from '#mui/material/styles';
function AddCatPopup({ breeds, isOpen, onClose, onAddCat }) {
const breedsName = breeds.map(item => item.nameBreed);
const colorsArray = [
'black',
'white',
'grey',
'red',
'multicolor'
];
const [name, setName] = React.useState('');
const [price, setPrice] = React.useState(0);
const [color, setColor] = React.useState('');
const [age, setAge] = React.useState(0);
const [breed, setBreed] = React.useState('');
function handleChange(event) {
const {
target: { value, id }
} = event;
id === "breed-select" ? setBreed(value) : setColor(value);
}
function handleSubmit(e) {
e.preventDefault();
}
return(
<section className={`popup ${isOpen && 'popup_opened'}`}>
<div className={'popup__container'}>
<button type="button" className={'popup__close-btn'} onClick={onClose}></button>
<p className={'popup__title'}>Enter info about cat</p>
<TextField sx={{ mt: 1, mb: 1 }}
id="standard-required"
variant="standard"
label="Name"
required />
<TextField sx={{ mt: 1, mb: 1 }}
id="standard-required"
variant="standard"
label="Price"
required />
<FormControl sx={{ mt: 1, mb: 1 }}
variant="standard"
required>
<InputLabel id="breed-label">Breed</InputLabel>
<Select
labelId="filter-breed"
id="breed-select"
label="Breed"
value={breed}
onChange={handleChange}
>
{breedsName.map((item) => (
<MenuItem
key={item}
value={item}
id="breed-select"
>
{item}
</MenuItem>
))}
</Select>
</FormControl>
<FormControl sx={{ mt: 1, mb: 1 }}
variant="standard"
required>
<InputLabel id="color-label">Color</InputLabel>
<Select
labelId="filter-color"
id="color-select"
label="Color"
value={color}
onChange={handleChange}
>
{colorsArray.map((item) => (
<MenuItem
key={item}
value={item}
id="color-select"
>
{item}
</MenuItem>
))}
</Select>
</FormControl>
<TextField sx={{ mt: 1, mb: 1 }}
id="standard-required"
variant="standard"
label="Age"
required />
<ThemeProvider theme={theme}>
<Button sx={{ mt: 1, mb: 1 }}
variant="contained"
color={'secondary'}
onClick={handleSubmit}>
Add
</Button>
</ThemeProvider>
</div>
</section>
);
}
export default AddCatPopup;
The main problem was that you doesn't get id and value correctly. I understand why you wrote this code, but unfortunately the event which come into handleChange is MouseEvent | PointerEvent so you could not get the correct id and value. The reason why you could choose color in this part id === "breed-select" ? setBreed(value) : setColor(value); you always got id = undefined so the setColor is fired always. You should use second argument of handleChange function. You can copypaste below code to see how does it work now
import React from "react";
import "./AddCatPopup.css";
import {
Button,
FormControl,
InputLabel,
MenuItem,
Select,
TextField
} from "#mui/material";
import { theme } from "./theme";
import { ThemeProvider } from "#mui/material/styles";
function AddCatPopup({ breeds, isOpen, onClose, onAddCat }) {
const breedsName = breeds.map((item) => item.nameBreed);
const colorsArray = ["black", "white", "grey", "red", "multicolor"];
const [name, setName] = React.useState("");
const [price, setPrice] = React.useState(0);
const [age, setAge] = React.useState(0);
const [color, setColor] = React.useState("");
const [breed, setBreed] = React.useState("");
function handleChange(event, obj) {
const target = object.props;
const id = target.id;
const value = target.value;
/breed-option/.test(id) ? setBreed(value) : setColor(value);
}
function handleSubmit(e) {
e.preventDefault();
}
return (
<section className={`popup ${isOpen && "popup_opened"}`}>
<div className={"popup__container"}>
<button
type="button"
className={"popup__close-btn"}
onClick={onClose}
></button>
<p className={"popup__title"}>Enter info about cat</p>
<TextField
sx={{ mt: 1, mb: 1 }}
id="standard-required"
variant="standard"
label="Name"
required
/>
<TextField
sx={{ mt: 1, mb: 1 }}
id="standard-required"
variant="standard"
label="Price"
required
/>
<FormControl sx={{ mt: 1, mb: 1 }} variant="standard" required>
<InputLabel id="breed-label">Breed</InputLabel>
<Select
labelId="filter-breed"
id="breed-select"
label="Breed"
value={breed}
onChange={handleChange}
>
{breedsName.map((item, index) => (
<MenuItem key={item} value={item} id={'breed-option-' + index}>
{item}
</MenuItem>
))}
</Select>
</FormControl>
<FormControl sx={{ mt: 1, mb: 1 }} variant="standard" required>
<InputLabel id="color-label">Color</InputLabel>
<Select
labelId="filter-color"
id="color-select"
label="Color"
value={color}
onChange={handleChange}
>
{colorsArray.map((item, index) => (
<MenuItem key={item} value={item} id={"color-option-" + index}>
{item}
</MenuItem>
))}
</Select>
</FormControl>
<TextField
sx={{ mt: 1, mb: 1 }}
id="standard-required"
variant="standard"
label="Age"
required
/>
<ThemeProvider theme={theme}>
<Button
sx={{ mt: 1, mb: 1 }}
variant="contained"
color={"secondary"}
onClick={handleSubmit}
>
Add
</Button>
</ThemeProvider>
</div>
</section>
);
}
export default AddCatPopup;

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

Categories

Resources