PREMISE
ok so this is my code in a screen named sliding dashboard which is a child component in chatScreen which I used to call all data sources and render a dropdown with these data sources
CODE
const SlidingDashboard = () => {
const [dashboardData, setDashboardData] = useState(null);
const [dataSources, setDataSources] = useState([]);
const [isDropDownDisabled, setIsDropDownDisabled] = useState(false);
const [dropdownData, setDropdownData] = useState([]);
const [defaultDropdownValue, setDefaultDropdownValue] = useState(null);
const [loading, setLoading] = useState(true);
const [jwtToken, setjwtToken] = useState();
console.log(jwtToken);
const [isDropDownLoading, setIsDropDownLoading] = useState(true);
const [error, setError] = useState(null);
const [stepsLoading, setStepsLoading] = useState(true);
const [caloriesLoading, setCaloriesLoading] = useState(true);
const [heartLoading, setHeartLoading] = useState(true);
const [isDragged, setIsDragged] = useState(false);
const slideAnim = useRef(new Animated.Value(height - fixedDistanceFromBottom)).current; // Start at the bottom
useEffect(() => {
const fetchMyData = async () => {
try {
setLoading(true);
setIsDropDownLoading(true);
const token = await AsyncStorage.getItem("jwtToken");
setjwtToken(token);
// console.log('Fetched token:', token);
const sourceResp = await fetch(`${BACKEND_URL}/user/userSources`, {
method: "GET",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
});
const sourceJson = await sourceResp.json();
const { success, message } = sourceJson || {};
// console.log('sourceJson:', sourceJson);
if (!success) {
console.log("error 1");
setError(message || "An error occurred while fetching data");
return;
}
const { data } = sourceJson.data || {};
if (data && data.sources) {
const sourceDetails = data.sources.map(({ id, defaultSource }) => ({
id,
defaultSource,
}));
setDataSources(sourceDetails);
if (!data.sources.length) {
setIsDropDownDisabled(true);
return;
} else {
setIsDropDownDisabled(false);
const serviceMapping = {
"66f61ffb-7493-49ff-8e64-ce130f4d693b": {
label: "Connected to Health Connect",
value: "health connect",
},
"86619ffb-b8f6-4a97-a6f9-fda30bca20cd": {
label: "Connected to Fitbit",
value: "fitbit",
},
};
const dropdownOptions = sourceDetails.map((source) => ({
label: serviceMapping[source.id]?.label || "Unknown",
value: serviceMapping[source.id]?.value || "unknown",
id: source.id,
}));
setDropdownData(dropdownOptions);
const defaultSource = sourceDetails.find((source) => source.defaultSource);
// console.log('default source is', defaultSource);
const defaultValue = defaultSource ? serviceMapping[defaultSource.id]?.value || null : null;
// console.log('defaultValue is', defaultValue);
setDefaultDropdownValue(defaultValue);
setIsDropDownLoading(false);
const sourceId = defaultSource ? defaultSource.id : sourceDetails[0]?.id;
// console.log('source id is', sourceId);
if (sourceId) {
const dashBoardResp = await fetch(`${BACKEND_URL}/user/dashboard/${sourceId}`, {
method: "GET",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
});
const dashBoardJson = await dashBoardResp.json();
if (dashBoardJson.success) {
setDashboardData(dashBoardJson.data);
setStepsLoading(false);
setCaloriesLoading(false);
setHeartLoading(false);
// console.log('dashboard dataz is', dashBoardJson);
} else {
setError(dashBoardJson.message || "Failed to fetch data");
console.log("API response error:", dashBoardJson.message || "Unknown error");
}
}
}
} else {
setIsDropDownDisabled(true); // Handle case where sources key is missing
setError("No sources available");
}
} catch (error) {
setError("An error occurred while fetching data");
console.log("Fetch error:", error.message);
} finally {
setLoading(false);
setIsDropDownLoading(false);
}
};
fetchMyData();
}, []);
// useEffect(() => {
// if (dataSources.length > 0) {
// setIsDropDownDisabled(false);
// } else {
// setIsDropDownDisabled(true);
// }
// }, [dataSources]);
const getServiceData = async (sourceID, tok) => {
try {
setLoading(true);
setStepsLoading(true);
setCaloriesLoading(true);
setHeartLoading(true);
const dashBoardResp = await fetch(`${BACKEND_URL}/user/dashboard/${sourceID}`, {
method: "GET",
headers: {
Authorization: `Bearer ${tok}`,
"Content-Type": "application/json",
},
});
const dashBoardJson = await dashBoardResp.json();
if (dashBoardJson.success) {
setDashboardData(dashBoardJson.data);
setStepsLoading(false);
setCaloriesLoading(false);
setHeartLoading(false);
// console.log('dashboard dataz is', dashBoardJson);
} else {
setError(dashBoardJson.message || "Failed to fetch data");
console.log("API response error:", dashBoardJson.message || "Unknown error");
}
} catch (error) {
setError("An error occurred while fetching data");
console.log("Fetch error:", error.message);
} finally {
setLoading(false);
}
};
const panResponder = useRef(
PanResponder.create({
onMoveShouldSetPanResponder: (evt, gestureState) => {
const { dx, dy } = gestureState;
return Math.abs(dy) > 10;
},
onPanResponderMove: (evt, gestureState) => {
slideAnim.setValue(Math.max(0, Math.min(height - fixedDistanceFromBottom, gestureState.moveY)));
},
onPanResponderRelease: (evt, gestureState) => {
if (dropdownRef.current && typeof dropdownRef.current.close === "function") {
dropdownRef.current.close(); // Close the dropdown
}
const newPosition = gestureState.moveY < height / 2 ? 0 : height - fixedDistanceFromBottom;
Animated.spring(slideAnim, {
toValue: newPosition,
useNativeDriver: false,
}).start();
},
}),
).current;
// ...
};
ISSUE
When I go to Add new device screen and successfully add a new device data sources increase and my dashboard should show this data but this doesnt happen and I have to press r to reload in dev mode or logout and login again in my app to see the new device data ie the screen has to re render once to show correct data
THINGS I TRIED
-
added dependencies of dataSources to useEffect and hit trial of other dependencies
Result: no effect of dataSources and other sometimes cause infinite re render
-
used useFocusEffect from react navigation so that when user focuses on screen then data is fetched
Result: No effect as even when screen comes in focus data is not refetched
-
used propDrilling: I thought if screen is not coming in focus and not re rendering so let me pass —data from parent component ChatScreen
Result: Infinite re render app is not readable: Error: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect,
-
I thought of one more fix that when dashboard is dragged to height/2 then call the api by modifying the pan responder
Result: Api doesnt even fetch and only my loading placeholders are shown
So what should I do now to fix or debug this problem