MUI, ReactSuite: Uncaught RangeError: Maximum call stack size exceeded - reactjs

I'm using Modal component from React Suite and Select component from MUI
Basically I have an open button that opens a modal popup which has inside, a select component
However, when I open console, it produces the following error when I open the modal and select something from the Select menu:
at HTMLDocument.contain (TrapFocus.js:214:1)
at Object.current (Modal.js:131:1)
at useEventCallback.js:19:1
at Object.current (Modal.js:139:1)
at HTMLDocument.<anonymous> (useEventCallback.js:19:1)
at HTMLDocument.contain (TrapFocus.js:214:1)
at Object.current (Modal.js:131:1)
at useEventCallback.js:19:1
at Object.current (Modal.js:139:1)
at HTMLDocument.<anonymous> (useEventCallback.js:19:1)
I have not edited anything except just copying and pasting the sample code from both the Modal and Select components(pasting it inside the <Modal.Body>) from React Suite and MUI respectively, any idea what's causing the error?
Thanks in advance
import React from "react";
import { Button, Modal, Toggle, ButtonToolbar } from "rsuite";
import OutlinedInput from "#mui/material/OutlinedInput";
import InputLabel from "#mui/material/InputLabel";
import MenuItem from "#mui/material/MenuItem";
import FormControl from "#mui/material/FormControl";
import ListItemText from "#mui/material/ListItemText";
import Select from "#mui/material/Select";
import Checkbox from "#mui/material/Checkbox";
const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
PaperProps: {
style: {
maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
width: 250,
},
},
};
const names = [
"Oliver Hansen",
"Van Henry",
"April Tucker",
"Ralph Hubbard",
"Omar Alexander",
"Carlos Abbott",
"Miriam Wagner",
"Bradley Wilkerson",
"Virginia Andrews",
"Kelly Snyder",
];
function Box() {
const [open, setOpen] = React.useState(false);
const handleOpen = () => setOpen(true);
const handleClose = () => setOpen(false);
const [personName, setPersonName] = React.useState([]);
const handleChange = (event) => {
const {
target: { value },
} = event;
setPersonName(
// On autofill we get a stringified value.
typeof value === "string" ? value.split(",") : value
);
};
return (
<div className="modal-container">
<ButtonToolbar>
<Button onClick={handleOpen}>Open</Button>
</ButtonToolbar>
<Modal open={open} onClose={handleClose}>
<Modal.Header>
<Modal.Title>Modal Title</Modal.Title>
</Modal.Header>
<Modal.Body>
<div>
<FormControl sx={{ m: 1, width: 300 }}>
<InputLabel id="demo-multiple-checkbox-label">Tag</InputLabel>
<Select
labelId="demo-multiple-checkbox-label"
id="demo-multiple-checkbox"
multiple
value={personName}
onChange={handleChange}
input={<OutlinedInput label="Tag" />}
renderValue={(selected) => selected.join(", ")}
MenuProps={MenuProps}
>
{names.map((name) => (
<MenuItem key={name} value={name}>
<Checkbox checked={personName.indexOf(name) > -1} />
<ListItemText primary={name} />
</MenuItem>
))}
</Select>
</FormControl>
</div>
</Modal.Body>
<Modal.Footer>
<Button onClick={handleClose} appearance="primary">
Ok
</Button>
<Button onClick={handleClose} appearance="subtle">
Cancel
</Button>
</Modal.Footer>
</Modal>
</div>
);
}
export default Box;

Not better way to solve this, but set this attribute disableEnforceFocus in your Modal tag.

Related

MUI Select Component Rendering Weirdly

I have a custom component that consist of 3 Select components. However Select's are not rendering correctly. Their labels are seen next to the Select components instead of inside/on top of the border. See this See this also It should have looked like this
I tested this component on a code sandbox and it was working but not sure why it is not working in my project. I have #mui/material: 5.11.9 and react: 18.2.0
My component:
import React from 'react';
import {
Button,
Menu,
MenuItem,
Select,
FormControl,
InputLabel,
} from '#mui/material';
const FilterComponent = () => {
const [open, setOpen] = React.useState(false);
const [modifiedValue, setModifiedValue] = React.useState('');
const [fileValue, setFileValue] = React.useState('');
const [numberValue, setNumberValue] = React.useState('');
const handleOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
const handleModifiedChange = (event) => {
setModifiedValue(event.target.value);
};
const handleFileChange = (event) => {
setFileValue(event.target.value);
};
const handleNumberChange = (event) => {
setNumberValue(event.target.value);
};
return (
<div>
<Button variant='contained' onClick={handleOpen}>
Filter
</Button>
<Menu
id='filter-menu'
anchorEl={open}
open={Boolean(open)}
onClose={handleClose}
>
<MenuItem>
<FormControl
variant='standard'
sx={{ m: 1, minWidth: 200 }}
>
<InputLabel>Modified</InputLabel>
<Select
value={modifiedValue}
onChange={handleModifiedChange}
>
<MenuItem value='Modified'>Modified</MenuItem>
<MenuItem value='Removed'>Removed</MenuItem>
<MenuItem value='Affected'>Affected</MenuItem>
</Select>
</FormControl>
</MenuItem>
<MenuItem>
<FormControl
variant='standard'
sx={{ m: 1, minWidth: 200 }}
>
<InputLabel>File</InputLabel>
<Select value={fileValue} onChange={handleFileChange}>
<MenuItem value='a.java'>a.java</MenuItem>
<MenuItem value='b.java'>b.java</MenuItem>
</Select>
</FormControl>
</MenuItem>
<MenuItem>
<FormControl
variant='standard'
sx={{ m: 1, minWidth: 200 }}
>
<InputLabel>Number</InputLabel>
<Select
value={numberValue}
onChange={handleNumberChange}
>
<MenuItem value={1}>1</MenuItem>
<MenuItem value={2}>2</MenuItem>
<MenuItem value={3}>3</MenuItem>
</Select>
</FormControl>
</MenuItem>
</Menu>
</div>
);
};
export default FilterComponent;

How to make select label always appear at top in MUI?

I want to create a material ui selector that label always appear at top. I added placeholder to select component. Here is what I want to do.
When not focusing to select component or at the beginning, it looks like this.Label overlaps the place holder.
What I want to create select label always seem at the top and not overlaps the placeholder.
Here is the code at codesandbox
CodeSandbox
import * as React from "react";
import MenuItem from "#mui/material/MenuItem";
import FormControl from "#mui/material/FormControl";
import Select from "#mui/material/Select";
import InputLabel from "#mui/material/InputLabel";
const names = ["Oliver Hansen", "Van Henry", "April Tucker", "Ralph Hubbard"];
export default function MultipleSelectPlaceholder() {
const [personName, setPersonName] = React.useState(null);
const handleChange = (event) => {
setPersonName(event.target.value);
};
return (
<div>
<FormControl sx={{ m: 1, width: 300, mt: 3 }}>
<InputLabel id="demo-simple-select-label">Age</InputLabel>
<Select
labelId="demo-simple-select-label"
label="Age"
displayEmpty
value={personName}
onChange={handleChange}
renderValue={(selected) => {
if (selected === null) {
return <em>Please Choose Name</em>;
}
return selected;
}}
>
<MenuItem value={null}>
<em>Clear</em>
</MenuItem>
{names.map((name) => (
<MenuItem key={name} value={name}>
{name}
</MenuItem>
))}
</Select>
</FormControl>
</div>
);
}
<script src="https://unpkg.com/#material-ui/core/umd/material-ui.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.1/umd/react-dom.production.min.js"></script>
https://codesandbox.io/s/multipleselectplaceholder-material-demo-forked-t06gm?file=/demo.js
Just add to Select:
notched={true} // Makes space between lines
and to InputLabel:
shrink={true} // Keeps label at top
For this purpose, you can simply pass shrink prop to the InputLabel component

Required Field in React Form not Requiring Text Entry

I have a subscription dialog form. I want the email field to be required, but I am currently able to submit my form with a blank email address (which would be a major problem for the client!). I have it marked as required in my code, but that doesn't seem to be translating to my UI.
I am using Material UI for styling.
Any pointers are sincerely appreciated :)
In the picture, see how I was able to click subscribe with no email address (the submit message appears after clicking subscribe).
import React from 'react';
import Button from '#material-ui/core/Button';
import { makeStyles } from '#material-ui/core/styles';
import TextField from '#material-ui/core/TextField';
import Dialog from '#material-ui/core/Dialog';
import DialogActions from '#material-ui/core/DialogActions';
import DialogContent from '#material-ui/core/DialogContent';
import DialogContentText from '#material-ui/core/DialogContentText';
import DialogTitle from '#material-ui/core/DialogTitle';
import Grid from '#material-ui/core/Grid';
import { Typography } from '#material-ui/core';
import { Form } from 'react-final-form';
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
padding: theme.spacing(2)
},
divider: {
marginBottom: theme.spacing(2)
}
}));
export default function SubscribeFormResults() {
const classes = useStyles();
const [open, setOpen] = React.useState(false);
const [formSubmitted, setFormSubmitted] = React.useState(false);
const onSubmit = async values => {
console.log('Submitting subscribe form!');
console.log('Subscribe form values:', values);
setFormSubmitted(true);
};
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
setFormSubmitted(false);
};
const validate = values => {
const errors = {};
if (!values.userEmail) {
errors.userEmail = 'Required';
}
return errors;
};
return (
<div>
<Button size="small" color="primary" onClick={handleClickOpen}>
Subscribe
</Button>
<Dialog open={open} onClose={handleClose} aria-labelledby="form-dialog-title">
<DialogTitle id="form-dialog-title">Subscribe</DialogTitle>
<DialogContent>
<Form
onSubmit={onSubmit}
initialValues={{ userEmail: 'johndoe#example.com', arn: 'Connect to Backend!' }}
validate={validate}
render={({ handleSubmit, form, submitting, pristine, values }) => (
<form onSubmit={handleSubmit} noValidate>
<DialogContentText>
To subscribe to this website, please enter your email address here. We will send updates
occasionally.
</DialogContentText>
<TextField
label="Email Address"
name="userEmail"
margin="none"
required={true}
fullWidth
/>
{formSubmitted && <Grid item xs={12}>
<Typography name='submitMessage' variant='subtitle1'>You have subscribed to AA-01-23-45-678901-2. {/* Connect to backend here */}</Typography>
</Grid>}
<DialogActions>
<Button /* onClick={handleClose} */ color="primary" type="submit" disabled={submitting}>
Subscribe
</Button>
<Button onClick={handleClose} color="primary">
Close
</Button>
</DialogActions>
</form>
)}
/>
</DialogContent>
</Dialog>
</div>
);
}
For future readers, I fixed this by removing the validation parameter from the Material UI, uppercase Form tag and enforced validation using the standard, lowercase form tag.

Material ui list of select item need to be selected

i have created selected box..using functional component...i am getting list of items from the back end, i am looping that list and showing in the front end....now i need to be selected item need to show in the box what i have selected...could any one help on this...
Please see my example code in this link https://codesandbox.io/s/gallant-water-fnqiv
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import InputLabel from "#material-ui/core/InputLabel";
import MenuItem from "#material-ui/core/MenuItem";
import FormControl from "#material-ui/core/FormControl";
import Select from "#material-ui/core/Select";
const useStyles = makeStyles(theme => ({
formControl: {
margin: theme.spacing(1),
minWidth: 120
},
selectEmpty: {
marginTop: theme.spacing(2)
}
}));
const lists = ["Ten", "twenty", "Thirty", "Fourty", "Fifity", "Sixty"];
export default function SimpleSelect() {
const classes = useStyles();
const [age, setAge] = React.useState("");
const inputLabel = React.useRef(null);
const [labelWidth, setLabelWidth] = React.useState(0);
React.useEffect(() => {
setLabelWidth(inputLabel.current.offsetWidth);
}, []);
const handleChange = event => {
setAge(event.target.value);
};
return (
<div>
<FormControl variant="outlined" className={classes.formControl}>
<InputLabel ref={inputLabel} id="demo-simple-select-outlined-label">
Age
</InputLabel>
<Select
labelId="demo-simple-select-outlined-label"
id="demo-simple-select-outlined"
value={age}
onChange={handleChange}
labelWidth={labelWidth}
>
<MenuItem value={""}>
{lists.map(item => {
<li>{item.list}</li>;
})}
</MenuItem>
</Select>
</FormControl>
</div>
);
}
There is no property in the array named, item.list , so you need to use item alone which itself gives the value you want.
Also make sure <MenuItem value={item}> is inside the lists.map() method..
Include return statement of the MenuItemis inside ofthe lists.map() method which throws error in your codesandbox link
And hence,
Change:
<MenuItem value={""}>
{lists.map(item => {
<li>{item.list}</li>;
})}
</MenuItem>
To:
{lists.map(item => {
return (
<MenuItem value={item}>
<li>{item}</li>
</MenuItem>
);
})}
Forked Codesandbox
you can try this-
<div>
<FormControl variant="outlined" className={classes.formControl}>
<InputLabel ref={inputLabel} id="demo-simple-select-outlined-label">
Age
</InputLabel>
<Select
labelId="demo-simple-select-outlined-label"
id="demo-simple-select-outlined"
value={age}
onChange={handleChange}
labelWidth={labelWidth}
>
{lists.map(item => (
<MenuItem value={item}>{item}</MenuItem>
))}
</Select>
</FormControl>
</div>
https://codesandbox.io/s/material-ui-select-m8lgt
Updated code sandbox link
Your MenuItem was wrong.
{lists.map(item => (
<MenuItem value={item}>{item}</MenuItem>
))}

react is not firing form onSubmit function

I'm trying to submit form onSubmitbut its not firing the this.commentSubmit function, if i take <form></form> out, use <Button onSubmit> function it works however i need the form wrapped around the Textfield for the backend to read the req.body.comment_body to work.
Comment.js
import React from "react";
import TextField from '#material-ui/core/TextField';
import Button from '#material-ui/core/Button';
const Comment = (props) => (
<form onSubmit={props.onSubmit}>
<TextField
type="text"
id="outlined-multiline-static"
label="Write A Comment"
multiline
name="comment_body"
value={props.commentBody}
rows="10"
fullWidth
margin="normal"
variant="outlined"
onChange={props.commentChange}
/>
<Button type="submit" variant="outlined" component="span" color="primary">
Post A Comment
</Button>
</form>
)
export default Comment;
Image Container Component
import React from "react";
import Button from '#material-ui/core/Button';
import Grid from '#material-ui/core/Grid';
import Typography from '#material-ui/core/Typography';
import Paper from '#material-ui/core/Paper';
import Divider from '#material-ui/core/Divider';
import Image from './Image';
import Axios from '../Axios';
import moment from 'moment';
import Comment from './Comment';
class ImageContainer extends React.Component{
state = {
isComment: false,
comment_body: ""
}
handleCommentChange = (e) => {
this.setState({
comment_body: e.target.value
})
}
writeComment = (id) => {
this.setState({
isComment: this.state.isComment ? '' : id // check if you state is filled to toggle on/off comment
})
}
commentSubmit = (e) => {
e.preventDefault();
console.log(this.state.comment_body); // doesn't get console.log
Axios.post('/images/newComment', this.state.comment_body).then( (response )=> {
const newComment = { ...response.data};
console.log(newComment);
this.setState({
comment_body: ''
})
})
}
render(){
const { img, deleteImg } = this.props
return(
<Grid item sm={12} md={12} style={{ margin: '30px 0px'}}>
<Paper style={{padding:'20px 20px'}}>
{/* // empty image_title */}
<Typography style={{ padding: '30px 5px', letterSpacing:'8px', textTransform:'uppercase'}} variant="h4" align="center">{img.image_title}</Typography>
<Divider style={{ width: '150px', margin:'10px auto', backgroundColor:'#000000'}} variant="middle" />
<Image image_url={img.img_url} />
<Typography variant="h6" align="center">{img.user.username}</Typography>
<Typography variant="h6" align="center">{moment(img.created_at).calendar()}</Typography>
<Button onClick ={() => this.writeComment(img.id)} variant="outlined" component="span" color="primary">
{this.state.isComment === img.id ? "Close" : "Write A Comment"}
</Button>
{/* here were prevent comments being selected for all items in the array, renders the comment form you clicked on. */}
{this.state.isComment === img.id ?
<Comment onSubmit={this.commentSubmit}
commentBody={this.state.comment_body }
commentChange={this.handleCommentChange}/>
: null}
{/* hide delete button when user enters comment */}
{!this.state.isComment ? <Button style={{margin: '0px 20px'}} onClick={deleteImg} variant="outlined" component="span" color="primary">
Delete
</Button> : null}
</Paper>
</Grid>
)
}
}
export default ImageContainer
Alternatively this works but i don't think the back end reads the comment_body value
import React from "react";
import TextField from '#material-ui/core/TextField';
import Button from '#material-ui/core/Button';
const Comment = (props) => {
// <form onSubmit={props.onSubmit}>
return(
<div>
<TextField
type="text"
id="outlined-multiline-static"
label="Write A Comment"
multiline
name="comment_body"
value={props.commentBody}
rows="10"
fullWidth
margin="normal"
variant="outlined"
onChange={props.commentChange}
/>
<Button onClick={props.onSubmit} type="submit" variant="outlined" component="span" color="primary">
Post A Comment
</Button>
</div>
);
// </form>
}
export default Comment;
backend
router.post('/newComment', async (req, res) => {
const comment = new Comment({
comment_body: req.body.comment_body,
user_id: req.user.id
})
comment.save().then( (comment) => {
return res.status(200).json(comment);
})
})
The problem lies with <Button> from Material-ui not being an actual button but rather a combination of a <span>. So if you have a type="submit" the form doesn't do anything.
If you change your material-ui <Button> to a native <button> it works as expected.
Here's an example: https://codesandbox.io/embed/56615445-fj6sc

Resources