Topic: MDBSelect Array of Options - Get Value Errors
datashield free asked 5 years ago
Hello,
I am attempting to use the Array of Options
version of the Select
component found here. The code I'm using is displayed below. Currently when I try to insert a function for getValue
or getTextContent
it produces the error Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
getDateRange
is being passed in from a parent element as returnValue
. It is shown below so you can understand the function I am passing.
getDateRange(value) {
const dateRange = value[0];
this.setState({dateRange});
}
Below shows the component getDateRange
is being passed to.
const Select = (props) => {
const { menuItems, multiple, search, color, label, returnValue } = props;
return (
<div>
<MDBSelect
multiple={multiple}
search={search}
color={color}
options={menuItems}
getValue={returnValue}
selected="Choose your option"
/>
<label>{label}</label>
</div>
);
};
It appears that the issue is that during componentDidMount
and componentDidUpdate
this function is being run automatically. This bug does not appear to occur on the non-array option version of the component.
Anna Morawska staff answered 5 years ago
Hi there,
thank you that you put the effort to prepare the working example. You have just run into an interesting problem here - please noticed that you declared options2 constant in the render method. This variable is accolated in the memory every time method runs, and it lives there ONLY when that method is running. So every re-render creates a new allocation in the memory, and it is passed down as a prop to the child component as an entirely different constant. As you probably know, prop changes triggers re-render of the component, so again new constat is declared, component understand it as a prop change and we have a formula for infinite loop here.
To solve this, you have to declare the options array somewhere outside the render method. One option is inside a state object, but there are other solutions too. Please check out the code snippet bellow:
import React, { Component } from "react";
import { MDBRow, MDBCol, MDBSelect } from 'mdbreact';
// const options2 = [
// { checked: true, value: '7', text: '7 Days' },
// { value: '30', text: '30 Days' },
// { value: '90', text: '90 Days' },
// { value: 'custom', text: 'Custom Range' },
// ];
class Scans extends Component {
constructor(props) {
super(props);
this.state = {
options: [
{ checked: true, value: '7', text: '7 Days' },
{ value: '30', text: '30 Days' },
{ value: '90', text: '90 Days' },
{ value: 'custom', text: 'Custom Range' },
],
};
this.getDateRange = this.getDateRange.bind(this);
}
getDateRange(value) {
const dateRange = value[0];
this.setState({ dateRange });
}
options2 = [
{ checked: true, value: '7', text: '7 Days' },
{ value: '30', text: '30 Days' },
{ value: '90', text: '90 Days' },
{ value: 'custom', text: 'Custom Range' },
];
render() {
const { getDateRange } = this;
const { options } = this.state;
return (
<div className="d-flex flex-column">
<MDBRow>
<MDBCol size="2">
{/* // Update this instance of options to options2 to produce error */}
<Select menuItems={this.options2} color="primary" label="Select" returnValue={getDateRange} />
</MDBCol>
</MDBRow>
</div>
);
}
}
const Select = (props) => {
const { menuItems, multiple, color, label, returnValue } = props;
return (
<div>
<MDBSelect
multiple={multiple}
color={color}
options={menuItems}
getValue={returnValue}
selected="Choose your option"
/>
<label>{label}</label>
</div>
);
};
export default Scans;
Ahmadjohn free answered 5 years ago
Hi any news on fixing this?
I'm trying to make a custom selection where you choose a different outfit option and it will give a different price value on the second form dropdown
Top
class Dashboard extends Component {
constructor(props) {
super(props);
this.state = {
outfits: "",
outfits_budget: "",
outfits14: "block",
outfits17: "none",
outfits2: "none",
Mid
};
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
onChange(e) {
this.setState({ [e.target.name]: e.target.value });
}
componentDidMount() {
if (!this.props.auth.isAuthenticated) {
this.props.history.push("/login");
}
if (this.props.auth.user.user_type == "1") {
this.props.history.push("/admin");
}
}
filterOutfits(e) {
e.preventDefault();
this.setState({ outfits: e.target.value, outfits_budget: "" });
switch (e.target.value) {
case "1 OUTFIT 4HRS":
this.setState({
outfits_budget: "",
outfits14: "block",
outfits17: "none",
outfits2: "none",
outfits3: "none",
outfits4: "none"
});
onSubmit(e) {
e.preventDefault();
const data = {
outfits: this.state.outfits,
outfits_budget: this.state.outfits_budget,
};
// console.log(data);
this.props.surveySubmit(data);
}
bottom
No. of Outfits 1 OUTFIT 4HRS 1 OUTFIT 7HRS 2 OUTFIT 3 OUTFIT 4 OUTFIT <div className="form-group col-md-6">
<MDBSelect
label="Outfits Budget"
name="outfits_budget"
id="outfits_budget"
required
onChange={this.onChange}
color="dark"
>
<MDBSelectInput selected="Outfits Budget" />
<MDBSelectOptions>
<MDBSelectOption disabled>Outfits Budget</MDBSelectOption>
<MDBSelectOption
value="600 - 990"
style={{ display: this.state.outfits14 }}
>
$600 - $990
</MDBSelectOption>
<MDBSelectOption
value="990 - 1200"
style={{ display: this.state.outfits14 }}
>
$990 - $1200
</MDBSelectOption>
<MDBSelectOption
value="1600 - 1900"
style={{ display: this.state.outfits17 }}
>
$1600 - $1900
</MDBSelectOption>
<MDBSelectOption
value="2100 - 2600"
style={{ display: this.state.outfits17 }}
>
$2100 - $2600
</MDBSelectOption>
<MDBSelectOption
value="2300 - 2600"
style={{ display: this.state.outfits2 }}
>
$2300 - $2600
</MDBSelectOption>
</MDBSelectOptions>
Piotr Glejzer staff commented 5 years ago
We will rewrite MDBSelect to a new component in the nearly future. There are a lot of bugs and we know about that. We are very sorry about these problems and we will fix this for sure with the new Material Select. Have a nice day.
dev.penpenn free answered 5 years ago
is this fu****g fix? i just encounter this tsk
Piotr Glejzer staff commented 5 years ago
Hi,
may you show me your code? I don't think it is fixed but I will try to help. Thanks.
Anna Morawska staff answered 5 years ago
Hi @stathisntonas,
unfortunately, it's a bug, I've added it our TODO list - we will try to fix this as soon as possible. Sorry for the inconvenience.
Best regards,
Ania
stathisntonas free answered 5 years ago
run into the exact same issue using #next
as a version from gitlab, I'm using nextjs.
I was preparing the options
in render and I run into maximum update depth ...
.
In componentDidMount
I'm fetching my data and then programmatically build the options
from the response.
example:
componentDidMount() {
let id = localStorage.getItem("_id");
axiosCallApi.get(`${apiUrl}/account/user/${id}`).then(response => {
const user = response.data;
const ranges = [
{
checked: user.comRange === 5000,
disabled: false,
icon: null,
value: 5000,
text: 5
},
{
checked: user.comRange === 10000,
disabled: false,
icon: null,
value: 10000,
text: 10
}
];
this.setState({ user, ranges });
});
}
handleDistanceChange = value => {
this.setState(
update(this.state, {
user: {
comRange: {
$set: value[0]
}
}
})
);
};
<MDBSelect
color="primary"
getValue={value =>
this.handleDistanceChange(value)
}
options={this.state.ranges}
selected="Choose your option"
/>
The issue comes from getValue
, it seems it infinite runs if the options
are inside render()
datashield free answered 5 years ago
Hello,
Thank you so much for explaining that. Having never run into it before I would have never guessed that was the issue. Again, thank you.
datashield free answered 5 years ago
Hello,
I did more research into this thanks to the information you provided. The code you provided works perfectly and I have been able to now reproduce the error consistently.
It seems that options need to be fed in from the state for some reason. Below is a code example that contains the same options in this.state.options
and options2
. If you update the code to contain menuItems={options2}
instead of menuItems={options}
you should be able to reproduce the error.
I am also console logging both of the values to compare the differences, at this time I can see none. I also ran JSON.stringify on both of the variables and compared the output text and there does not appear to be a difference.
import React, { Component } from "react";
import { MDBRow, MDBCol, MDBSelect } from 'mdbreact';
class Scans extends Component {
constructor(props) {
super(props);
this.state = {
options: [
{ checked: true, value: '7', text: '7 Days' },
{ value: '30', text: '30 Days' },
{ value: '90', text: '90 Days' },
{ value: 'custom', text: 'Custom Range' },
],
};
this.getDateRange = this.getDateRange.bind(this);
}
getDateRange(value) {
const dateRange = value[0];
this.setState({ dateRange });
}
render() {
const { getDateRange } = this;
const { options } = this.state;
const options2 = [
{ checked: true, value: '7', text: '7 Days' },
{ value: '30', text: '30 Days' },
{ value: '90', text: '90 Days' },
{ value: 'custom', text: 'Custom Range' },
];
console.log(options);
console.log(options2);
return (
<div className="d-flex flex-column">
<MDBRow>
<MDBCol size="2">
// Update this instance of options to options2 to produce error
<Select menuItems={options} color="primary" label="Select" returnValue={getDateRange} />
</MDBCol>
</MDBRow>
</div>
);
}
}
const Select = (props) => {
const { menuItems, multiple, color, label, returnValue } = props;
return (
<div>
<MDBSelect
multiple={multiple}
color={color}
options={menuItems}
getValue={returnValue}
selected="Choose your option"
/>
<label>{label}</label>
</div>
);
};
export default Scans;
Anna Morawska staff answered 5 years ago
Hi there,
I have tried to reproduce your problem, but it looks like everything works fine. Please try the code presented above:
import React, { Component } from "react";
import { MDBSelect } from "mdbreact";
class App extends Component {
state = {
options: [
{
checked: false,
disabled: false,
icon: null,
text: "Option one"
},
{
checked: false,
disabled: false,
icon: null,
text: "Option two"
},
{
checked: true,
disabled: false,
icon: null,
text: "Option three"
},
{
checked: false,
disabled: false,
icon: null,
text: "Option four"
}
]
};
getDateRange = (value) =>{
const dateRange = value[0];
this.setState({dateRange}, () => console.log(this.state));
}
render(){
return (
<div>
<Select menuItems={this.state.options} multiple={false} search={false} color="primary" label="Select" returnValue={this.getDateRange} />
</div>
);
}
};
const Select = (props) => {
const { menuItems, multiple, color, label, returnValue } = props;
return (
<div>
<MDBSelect
multiple={multiple}
color={color}
options={menuItems}
getValue={returnValue}
selected="Choose your option"
/>
<label>{label}</label>
</div>
);
};
export default App;
FREE CONSULTATION
Hire our experts to build a dedicated project. We'll analyze your business requirements, for free.
Answered
- ForumUser: Free
- Premium support: No
- Technology: MDB React
- MDB Version: 4.8.4
- Device: Laptop
- Browser: Google Chrome 71.0.3578.98
- OS: Windows 10
- Provided sample code: Yes
- Provided link: Yes