health score: move the non-food early return past the hook
`if (!isEdible(category)) return null` sat on the line above `useQuery`, which made the hook conditional. React counts hooks per component instance, so one drawer reused for two products -- a soap and then a biscuit, which is ordinary browsing in the global catalogue -- went 0 hooks then 1 and threw "rendered more hooks than during the previous render". That does not degrade the panel, it unmounts the tree: the health score then disappears for EVERY product until the page is reloaded, which reads exactly like the feature having been switched off. The guard now sits after the hook, and `enabled` carries the intent the early return was protecting -- a non-food product still asks the service nothing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -56,14 +56,25 @@ export function HealthScorePanel({
|
|||||||
populated for both, so nothing in the response separates them. Our own
|
populated for both, so nothing in the response separates them. Our own
|
||||||
category does, so the decision is made here until they publish theirs.
|
category does, so the decision is made here until they publish theirs.
|
||||||
|
|
||||||
Before the network call, deliberately: there is nothing to ask about.
|
Still no network call for one — see `enabled` below — but the EARLY RETURN
|
||||||
|
that used to sit here has moved past the hook.
|
||||||
|
|
||||||
|
It read `if (!isEdible(category)) return null` on the line above `useQuery`,
|
||||||
|
which made the hook conditional. React counts hooks per component instance, so
|
||||||
|
one drawer reused for two products — a soap and then a biscuit, which is
|
||||||
|
ordinary browsing in the global catalogue — went 0 hooks then 1, and React
|
||||||
|
threw "rendered more hooks than during the previous render". That does not
|
||||||
|
degrade the panel, it unmounts the tree: the health score then disappears for
|
||||||
|
EVERY product until the page is reloaded, which reads exactly like the feature
|
||||||
|
being switched off.
|
||||||
*/
|
*/
|
||||||
if (!isEdible(category)) return null;
|
const isFood = isEdible(category);
|
||||||
|
|
||||||
const query = useQuery({
|
const query = useQuery({
|
||||||
queryKey: ['nutrition', brand, imageId],
|
queryKey: ['nutrition', brand, imageId],
|
||||||
queryFn: () => nutritionApi.forProduct(brand, imageId),
|
queryFn: () => nutritionApi.forProduct(brand, imageId),
|
||||||
enabled: Boolean(brand && imageId),
|
// Non-food asks nothing, which is what the early return was protecting.
|
||||||
|
enabled: Boolean(brand && imageId && isFood),
|
||||||
// Nutrition for a packaged product does not change during a trading day.
|
// Nutrition for a packaged product does not change during a trading day.
|
||||||
staleTime: 60 * 60_000,
|
staleTime: 60 * 60_000,
|
||||||
refetchOnWindowFocus: false,
|
refetchOnWindowFocus: false,
|
||||||
@@ -72,6 +83,9 @@ export function HealthScorePanel({
|
|||||||
retry: false,
|
retry: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Past the hook, so the count is the same on every render.
|
||||||
|
if (!isFood) return null;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* No catalogue link, so there is nothing to look up.
|
* No catalogue link, so there is nothing to look up.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user