Meteor newbie here, I have list loop that does a meteor call to the meteor method. I need the results populated in another object with each list item as key and value as the meteor method response. After all the item related meteor calls are done returning responses, I want to print the completely updated object in the end
This is my following code and it runs in an infinite loop
const [codeCoverage, setcodeCoverage] = useState({});
projectList = ['proj1','proj2','proj3']
projectList.map((project) => {
Meteor.call(
'sonarqb.getProjectStatus',
{ project },
(error, resp) => {
if (error) throw new Error(error);
setCodeCoverage({...codeCoverage, [project] : val.actualValue })
}
)
});
useEffect(() => {
console.log(codeCoverage);
}, [codeCoverage]);
Meteor Method serving the above call
Meteor.methods({
'sonarqb.getProjectStatus'({ project }) {
const options = {
method: 'GET',
url: `https://sonarqube.com/sonar/api/qualitygates/project_status?projectKey=${project}`,
headers: {
Authorization:
'Basic <auth str>',
},
};
const future = new Future();
request(options, function(error, response) {
if (error) throw new Error(error);
const sonarResponse = JSON.parse(response.body);
future.return(sonarResponse);
});
return future.wait();
},
});
Assuming this is a React function component, the issue is that your Meteor.call
s happen every time the component renders, which includes every time you call setCodeCoverage
, i.e., every time a call completes — hence an infinite loop.
You need to wrap the Meteor.call
s in a useEffect
(or something), not have them at the top level of your component. If you want them to just happen once at the beginning of your component:
const [codeCoverage, setcodeCoverage] = useState({});
const projectList = ['proj1','proj2','proj3'];
useEffect(() => {
projectList.forEach((project) => {
Meteor.call(
'sonarqb.getProjectStatus',
{ project },
(error, resp) => {
if (error) throw new Error(error);
setCodeCoverage((previous) =>
{...previous, [project] : val.actualValue });
}
)
})
}, []); // no deps => run once at beginning
useEffect(() => {
console.log(codeCoverage);
}, [codeCoverage]);