Reputation: 23
I'm building an App with the MERN Stack and right now it only searches for some data on the DB and print it on the page, but I'm getting this error when running the code:
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.
It says it's coming from Module../src/index.js, but I can't see any issues in there.
3 | import App from "./App";
4 | import * as serviceWorker from "./serviceWorker";
5 |
> 6 | ReactDOM.render(
7 | <React.StrictMode>
8 | <App />
9 | </React.StrictMode>,
I thought it could be coming from a function or an action on the components, but also couldn't see any infinite loop there. After some testing, I found out it fired off when this component is called:
./src/components/EntryModal.js
import React, { Component } from "react";
import {
Button,
Modal,
ModalBody,
ModalHeader,
Form,
FormGroup,
// FormFeedback,
Label,
Input,
NavLink,
} from "reactstrap";
import { connect } from "react-redux";
import { addEntry } from "../actions/obsActions";
import { clearErrors } from "../actions/errorActions";
import PropTypes from "prop-types";
export class EntryModal extends Component {
state = {
modal: false,
horaLeitura: [],
pressaoAtm: 0,
tempAr: 0,
tempMin: 0,
tempMax: 0,
umidRel: 0,
umidMin: 0,
radGlobal: 0,
chDia: 0,
ventoInten: 0,
ventoDirecao: "",
};
static propTypes = {
error: PropTypes.object.isRequired,
clearErrors: PropTypes.func.isRequired,
};
componentDidUpdate(prevProps) {
const { error } = this.props;
if (error !== prevProps.error) {
// Check for register error
if (error.id === "LOGIN_FAIL") {
this.setState({ msg: error.msg.msg });
} else {
this.setState({ msg: null });
}
}
this.toggle();
}
toggle = () => {
// Clear errors
this.props.clearErrors();
this.setState({
modal: !this.state.modal,
});
};
onChange = (e) => {
this.setState({ [e.target.name]: e.target.value });
};
onSubmit = (e) => {
e.preventDefault();
const {
horaLeitura,
pressaoAtm,
tempAr,
tempMin,
tempMax,
umidRel,
umidMin,
radGlobal,
chDia,
ventoInten,
ventoDirecao,
} = this.state;
const newEntry = {
horaLeitura,
pressaoAtm,
tempAr,
tempMin,
tempMax,
umidRel,
umidMin,
radGlobal,
chDia,
ventoInten,
ventoDirecao,
};
// Add Entry via addEntry action
this.props.addEntry(newEntry);
};
render() {
return (
<div>
<NavLink onClick={this.toggle} href="#">
Inserir dados
</NavLink>
<Modal isOpen={this.state.modal} toggle={this.toggle}>
<ModalHeader toggle={this.toggle}>Inserir observação</ModalHeader>
<ModalBody>
<Form onSubmit={this.onSubmit}>
<FormGroup>
<Label className="lead">Horário local da leitura</Label>
<Input
type="datetime"
name="horaLeitura"
id="hora-leitura"
placeholder="15jan2019/14:30h"
onChange={this.onChange}
/>
<Label className="lead">Pressão atmosférica</Label>
<Input
type="text"
name="pressaoAtm"
id="pressao-atm"
placeholder="1012.9"
onChange={this.onChange}
/>
<Label className="lead">Temperaturas (ar/min/max)</Label>
<Input
type="text"
name="tempAr"
id="temp-ar"
className="temperatura"
placeholder="°C ar"
onChange={this.onChange}
/>
<Input
type="text"
name="tempMin"
id="temp-min"
className="temperatura"
placeholder="mínima"
onChange={this.onChange}
/>
<Input
type="text"
name="tempMax"
id="temp-max"
className="temperatura"
placeholder="máxima"
onChange={this.onChange}
/>
<Label className="lead">Umidade (relativa/mín)</Label>
<Input
type="number"
name="umidRel"
id="umid-rel"
placeholder="relativa"
onChange={this.onChange}
/>
<Input
type="number"
name="umidMin"
id="umid-min"
placeholder="mínima"
onChange={this.onChange}
/>
<Label className="lead">Radiação solar global</Label>
<Input
type="number"
name="radGlobal"
id="rad-global"
placeholder="399"
onChange={this.onChange}
/>
<Label className="lead">Chuva acumulada no dia</Label>
<Input
type="text"
name="chDia"
id="ch-ac-dia"
placeholder="dia"
/>
<Label className="lead">Vento (intensidade/direção)</Label>
<Input
type="text"
name="ventoInten"
id="vento-inten"
placeholder="intensidade"
onChange={this.onChange}
/>
<Input
type="select"
name="ventoDirecao"
id="vento-dir"
placeholder="direção"
onChange={this.onChange}
>
<option value="opt-E">E: este/leste</option>
<option value="opt-N">N: norte</option>
<option value="opt-O">O: oeste</option>
<option value="opt-S">S: sul</option>
<option value="opt-NE">NE: nordeste</option>
<option value="opt-NO">NO: noroeste</option>
<option value="opt-SE">SE: sudeste</option>
<option value="opt-SO">SO: sudoeste</option>
<option value="opt-ENE">ENE: lés-nordeste</option>
<option value="opt-ESE">ESE: lés-sudeste</option>
<option value="opt-SSE">SSE: sul-sudeste</option>
<option value="opt-NNE">NNE: nor-nordeste</option>
<option value="opt-NNO">NNO: nor-noroeste</option>
<option value="opt-SSO">SSO: sul-sudoeste</option>
<option value="opt-OSO">OSO: oés-sudoeste</option>
<option value="opt-ONO">ONO: oés-noroeste</option>
</Input>
<Button style={{ marginTop: "2rem" }} color="secondary" block>
Gravar dados
</Button>
</FormGroup>
</Form>
</ModalBody>
</Modal>
</div>
);
}
}
const mapStateToProps = (state) => ({
entry: state.entry,
error: state.error,
});
export default connect(mapStateToProps, { addEntry, clearErrors })(EntryModal);
I'm sort of new to React, Redux and all, so if you could explain the error and it's solution it would be awesome.
Upvotes: 0
Views: 301
Reputation: 84
Don't use this.toggle function inside componentDidUpdate because when it's called the state is updated so the componentDidUpdate is called again and again this causes the infinite loop instead use this.toggle either on some button or componentDidMount .
Upvotes: 1
Reputation: 361
You're calling this.toggle() within componentDidUpdate, which modifies the state causing a re-render thus componentDidUpdate to run again, modifying the state.... This is the infinite loop.
Upvotes: 0