diff --git a/frontend/src/components/dashboard/ActionQueueCard.tsx b/frontend/src/components/dashboard/ActionQueueCard.tsx index 700b9a67..f802a61a 100644 --- a/frontend/src/components/dashboard/ActionQueueCard.tsx +++ b/frontend/src/components/dashboard/ActionQueueCard.tsx @@ -8,7 +8,7 @@ * about why each action is needed and what happens if they don't do it. */ -import React, { useState } from 'react'; +import React, { useState, useMemo } from 'react'; import { FileText, AlertCircle, @@ -71,9 +71,17 @@ function ActionItemCard({ const { t } = useTranslation('reasoning'); // Translate reasoning_data (or fallback to deprecated text fields) - const { reasoning, consequence, severity } = action.reasoning_data - ? formatPOAction(action.reasoning_data) - : { reasoning: action.reasoning || '', consequence: action.consequence || '', severity: '' }; + // Memoize to prevent undefined values from being created on each render + const { reasoning, consequence, severity } = useMemo(() => { + if (action.reasoning_data) { + return formatPOAction(action.reasoning_data); + } + return { + reasoning: action.reasoning || '', + consequence: action.consequence || '', + severity: '' + }; + }, [action.reasoning_data, action.reasoning, action.consequence, formatPOAction]); return (
{ + if (item.reasoning_data) { + return formatBatchAction(item.reasoning_data); + } + return { reasoning: item.reasoning || '' }; + }, [item.reasoning_data, item.reasoning, formatBatchAction]); const startTime = item.plannedStartTime ? new Date(item.plannedStartTime).toLocaleTimeString('en-US', { diff --git a/frontend/src/hooks/useReasoningTranslation.ts b/frontend/src/hooks/useReasoningTranslation.ts index d1652643..ce4476e6 100644 --- a/frontend/src/hooks/useReasoningTranslation.ts +++ b/frontend/src/hooks/useReasoningTranslation.ts @@ -5,6 +5,7 @@ * user-friendly, multilingual text for the JTBD dashboard. */ +import { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; export interface ReasoningData { @@ -135,7 +136,7 @@ export function useReasoningTranslation() { export function useReasoningFormatter() { const translation = useReasoningTranslation(); - const formatPOAction = (reasoningData?: ReasoningData) => { + const formatPOAction = useCallback((reasoningData?: ReasoningData) => { if (!reasoningData) { return { reasoning: translation.translatePOReasonng({} as ReasoningData) || 'Purchase order required', @@ -153,9 +154,9 @@ export function useReasoningFormatter() { consequence, severity }; - }; + }, [translation]); - const formatBatchAction = (reasoningData?: ReasoningData) => { + const formatBatchAction = useCallback((reasoningData?: ReasoningData) => { if (!reasoningData) { return { reasoning: translation.translateBatchReasoning({} as ReasoningData) || 'Production batch scheduled', @@ -170,7 +171,7 @@ export function useReasoningFormatter() { reasoning, urgency }; - }; + }, [translation]); return { formatPOAction,