Reputation:
I want to get input from a user and compare it with the response I am getting from API, and conditionally render the information if it match or just show a sorry message,(the API only contain 1 set of a data object including 4 value) let me know what am I missing.
here is my code
import React, { useState } from "react";
import axios from "axios";
function Form() {
const [vatInput, setVatInput] = useState("");
const [responseVatState, setResponseVatState] = useState("");
const [responseCountryCodeState, setResponseCountryCodeState] = useState("");
const [result, setResult] = useState(false);
const handelVatState = (event) => {
setVatInput(event.target.value);
};
const closeModalHandler = () => {
setResult(false);
};
const onFormSubmit = (event) => {
event.preventDefault();
axios
.get("Some URL")
.then((response) => {
setResponseVatState(response.data.response.data.VATNumber);
setResponseCountryCodeState(response.data.CountryCode);
})
.catch((error) => {
console.log(error);
});
};
const inputCountryCode = vatInput.substring(0, 2);
const inputVatCode = vatInput.substring(2);
if (
inputCountryCode === responseCountryCodeState &&
inputVatCode === responseVatState
) {
setResult(true);
} else {
setResult(false);
}
return (
<div >
<h4>VAT Validator</h4>
<form onSubmit={onFormSubmit}>
<label className="text-muted">Please Enter A Vat Number:</label>
<input
type="text"
name="VatInput"
placeholder="Please Enter A Vat Number"
onChange={handelVatState}
/>
<br />
<input type="submit" value="Let'Go" />
</form>
<label className="text-muted">Result : </label>
{result ? (
<div>{vatInput}</div>
) : (
<div clicked={closeModalHandler}>
<span> Sorry !!! Please Insert corect VAT Number</span>
</div>
)}
</div>
);
}
export default Form;
and the error is
react-dom.development.js:14997 Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
so I get the input from the user and set it with hooks, then with Axios call get my data, then I split the string with
const inputCountryCode = vatInput.substring(0, 2);
const inputVatCode = vatInput.substring(2);
to compare with the input I have, if it's the same then render the data if not just render the sorry message
Upvotes: 1
Views: 908
Reputation: 5695
You have a couple of issues, the main of which resulting in Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
is due to an infinite loop of component re-rendering, which you force by setting state directly in the function body.
More specifically, this code:
if (
inputCountryCode === responseCountryCodeState &&
inputVatCode === responseVatState
) {
setResult(true);
} else {
setResult(false);
}
force react to re-evaluate the component because you're changing its state by using setResult
. When react starts rendering the new body it yet again encounters setResult
which results in a new update and re-render which, as you see, leads to a never-ending loop.
Furthermore, you don't need to save the request response to the component state at all, as it is relevant just for the calculation, which is needed only in the form submit handler itself. So, you should ditch the
const [responseVatState, setResponseVatState] = useState("");
const [responseCountryCodeState, setResponseCountryCodeState] = useState("");
state variables altogether. The only state you need except the input value is the validation result.
Also, you have a typo: setResponseVatState(response.data.response.data.VATNumber);
should be setResponseVatState(response.data.VATNumber);
.
Try this:
import React, { useState } from "react";
import axios from "axios";
function Form() {
const [vatValue, setVatValue] = useState("");
const [isVatValid, setIsVatValid] = useState(false);
const handelVatState = (event) => {
setVatValue(event.target.value);
};
const closeModalHandler = () => {
setIsVatValid(false);
};
const onFormSubmit = (event) => {
event.preventDefault();
axios
.get("[URL]")
.then((response) => {
const inputCountryCode = vatValue.substring(0, 2);
const inputVatCode = vatValue.substring(2);
const { VATNumber, CountryCode } = response.data;
if (inputCountryCode === CountryCode && inputVatCode === VATNumber) {
setIsVatValid(true);
}
else {
setIsVatValid(false);
}
})
.catch((error) => {
console.log(error);
});
};
return (
<div >
<h4>VAT Validator</h4>
<form onSubmit={onFormSubmit}>
<label className="text-muted">Please Enter A Vat Number:</label>
<input
type="text"
name="VatInput"
placeholder="Please Enter A Vat Number"
onChange={handelVatState}
/>
<br />
<input type="submit" value="Let'Go" />
</form>
<label className="text-muted">Result : </label>
{isVatValid ? (
<div>{vatValue}</div>
) : (
<div clicked={closeModalHandler}>
<span> Sorry !!! Please Insert corect VAT Number</span>
</div>
)}
</div>
);
}
export default Form;
Also, I suppose <div clicked={closeModalHandler}>
should be <div onClick={closeModalHandler}>
?
Here is your solution after comments:
import React, { useState } from "react";
import axios from "axios";
function Form() {
const [vatValue, setVatValue] = useState("");
const [isVatValid, setIsVatValid] = useState(null);
const handelVatState = (event) => {
setVatValue(event.target.value);
};
const closeModalHandler = () => {
setIsVatValid(null);
};
const onFormSubmit = (event) => {
event.preventDefault();
axios
.get("https://vat.erply.com/numbers?vatNumber=BG999999999")
.then((response) => {
const inputCountryCode = vatValue.substring(0, 2);
const inputVatCode = vatValue.substring(2);
const { VATNumber, CountryCode } = response.data;
if (inputCountryCode === CountryCode && inputVatCode === VATNumber) {
setIsVatValid(true);
}
else {
setIsVatValid(false);
}
})
.catch((error) => {
console.log(error);
});
};
const getResultRepresentation = () => {
if (isVatValid === null) {
return null;
}
if (isVatValid) {
return (
<>
<label className="text-muted">Result: </label>
<div>{vatValue}</div>
</>
);
}
else {
return (
<div onClick={closeModalHandler}>
<span> Sorry !!! Please Insert corect VAT Number</span>
</div>
);
}
}
return (
<div >
<h4>VAT Validator</h4>
<form onSubmit={onFormSubmit}>
<label className="text-muted">Please Enter A Vat Number:</label>
<input
type="text"
name="VatInput"
placeholder="Please Enter A Vat Number"
value={vatValue} // <= missing
onChange={handelVatState}
/>
<br />
<input type="submit" value="Let'Go" />
</form>
{getResultRepresentation()}
</div>
);
}
export default Form;
And here is a CodeSandbox to test it out.
Upvotes: 1