Firstly, I appreciate my explanation might not be the most accurate.
TL;DR: the last setAllSdksInfo(objCopy)
won’t work at the end of the code, while console.log just before it will print what should have been set. I believe it’s due to the asynchronous calls I’m making.
I’m working on an app that compare SDKS (their churn and acquisition rates). I have created an API with two separate endpoints.
- The first, compares one sdk to another and spits out that data aboth both sdks, how they relate.
- The second, simply gets general information about a single sdk.
I’m merging these objects into one, so that all information regarding a single SDK can be found.
PROBLEM: When setting the object at the end with setAllSdksInfo(objCopy) it simply won’t set the object.
I’m getting an ESLint warning which might be related to the problem:
Function declared in a loop contains unsafe references to variable(s)
'objCopy', 'objCopy', 'objCopy', 'objCopy', 'objCopy', 'objCopy', 'objCopy'
import React, { useEffect } from "react";
import MatrixSquare from "./MatrixSquare";
function Matrix({ selectedSdks, allSdksInfo, setAllSdksInfo, showMatrix, setShowMatrix }) {
useEffect(() => {
(async () => {
const selectedSdksKeys = Object.keys(selectedSdks);
if (!selectedSdksKeys.length) return;
setShowMatrix(false);
let comparedCount = 0;
const notComparedKeys = [];
selectedSdksKeys.forEach((key, i) => {
for (let j = i + 1; j < selectedSdksKeys.length; j++) {
if ( allSdksInfo?.[key]?.["churned_to"]?.hasOwnProperty( selectedSdksKeys[j])) {
comparedCount += 1;
if (comparedCount === 3) {
setShowMatrix(true);
}
} else {
notComparedKeys.push([key, selectedSdksKeys[j]]);
}
}
});
let objCopy = Object.assign({}, allSdksInfo);
for (let i = 0; i < notComparedKeys.length; i++) {
await fetch( `/api/sdk/churn?sdk1_id=${notComparedKeys[i][0]}&sdk2_id=${notComparedKeys[i][1]}`)
.then((res) => res.json())
.then((res) => {
const copyPreviousObj = Object.assign({}, objCopy);
objCopy = { ...objCopy, ...res };
const resKeys = Object.keys(res);
resKeys.forEach((key) => {
const new_churned_to = objCopy[key]["churned_to"];
const new_acquired_from = objCopy[key]["acquired_from"];
if (copyPreviousObj[key]) {
objCopy[key]["churned_to"] = {
...new_churned_to,
...copyPreviousObj[key]["churned_to"],
};
objCopy[key]["acquired_from"] = {
...new_acquired_from,
...copyPreviousObj[key]["acquired_from"],
};
}
});
});
}
selectedSdksKeys.forEach(async (id, i) => {
if (allSdksInfo[id]?.["num_installed_apps"]) return;
const res = await fetch(`/api/sdk/general_info?sdk_id=${id}`);
const data = await res.json();
objCopy[id]["num_installed_apps"] = data["num_installed_apps"];
objCopy[id]["acquired_total"] = data["acquired_total"];
objCopy[id]["churned_total"] = data["churned_total"];
});
console.log(objCopy) // ***************** PRINTS obj OK =)
setAllSdksInfo(objCopy);
console.log(allSdksInfo) // ************** PRINTS EMPTY OBJECT =(
setShowMatrix(true);
})();
}, [selectedSdks]);
Source: Ask Javascript Questions