I have read all the docs, found situations similar to mine but never found a solution that applies.
This component receives a prop from the parent props.measurementsArray
which it sends to an API in useEffect, storing the results in state (setCentile_data
). The measurementsArray is made up of objects (each containing growth data) and I loop through the array, making an API call for each, adding the results to centile_data
.
function ChartData(props) {
const [isLoading, setLoading] = useState(true);
const [centile_data, setCentile_data] = useState([]);
const measurementsArray = props.measurementsArray;
const reference = props.reference;
useEffect(() => {
const fetchCentilesForMeasurement = async (payload, reference) =>{
let url
if (reference === "uk-who"){
url = `${process.env.REACT_APP_GROWTH_API_BASEURL}/uk-who/calculation`
}
if (reference === "turner"){
url = `${process.env.REACT_APP_GROWTH_API_BASEURL}/turner/calculation`
}
if (reference === "trisomy-21"){
url = `${process.env.REACT_APP_GROWTH_API_BASEURL}/trisomy-21/calculation`
}
const response = await axios({
url: url,
data: payload,
method: "POST",
headers: {
"Content-Type": "application/json",
},
});
return response.data;
}
let ignore = false; // this prevents data being added to state if unmounted
if (measurementsArray.length > 0) {
try {
measurementsArray.forEach(measurement => {
fetchCentilesForMeasurement(measurement, reference).then((result) => {
if (!ignore) {
// this prevents data being added to state if unmounted
setCentile_data(centile_data => [...centile_data, result])
}
}).then(()=>{
setLoading(false)
}).catch((error)=>{
console.log(error.message);
setCentile_data([])
setLoading(false)
});
});
} catch (error) {
console.error("Failure!");
console.error(error.response.status);
alert("The server is not responding. Sorry.");
if (!ignore) {
setLoading(false);
}
}
} else {
if (!ignore) {
setLoading(false);
}
}
return () => {
ignore = true;
}; // this prevents data being added to state if unmounted
}, []);
render (...)
The difficulty is that I am setting centile_data
in useEffect
which causes the component to rerender, creating a loop. Passing in dependencies suggested by the linter (as per the documentation), or []
has no effect. I would be grateful if someone could set me straight about the howling error I am making.
So my apologies. This code it turns out is fine but there was an error in a component further down the tree. Life lesson for me, sorry to waste time.