From c883d5b7e9e1c07e1725bb8ac84cd77c2a23796a Mon Sep 17 00:00:00 2001 From: PeterYurkovich Date: Tue, 16 Jun 2026 07:19:32 -0400 Subject: [PATCH] lint: refactor to remove some of the set-state-in-effect overrides --- .../Incidents/AlertsChart/AlertsChart.tsx | 43 +++++++++++++------ .../IncidentsChart/IncidentsChart.tsx | 34 ++++++++++----- .../public/components/autocomplete.tsx | 26 +++++------ 3 files changed, 66 insertions(+), 37 deletions(-) diff --git a/web/src/components/Incidents/AlertsChart/AlertsChart.tsx b/web/src/components/Incidents/AlertsChart/AlertsChart.tsx index 5751b32b9..c8c7d1882 100644 --- a/web/src/components/Incidents/AlertsChart/AlertsChart.tsx +++ b/web/src/components/Incidents/AlertsChart/AlertsChart.tsx @@ -42,10 +42,11 @@ import { MonitoringState } from '../../../store/store'; import { isEmpty } from 'lodash-es'; import { DataTestIDs } from '../../data-test'; +export const DEFAULT_CHART_CONTAINER_HEIGHT = 300; +export const DEFAULT_CHART_HEIGHT = 250; + const AlertsChart = ({ theme }: { theme: 'light' | 'dark' }) => { const dispatch = useDispatch(); - const [chartContainerHeight, setChartContainerHeight] = useState(); - const [chartHeight, setChartHeight] = useState(); const alertsData = useSelector( (state: MonitoringState) => state.plugins.mcp.incidentsData.alertsData, ); @@ -71,16 +72,34 @@ const AlertsChart = ({ theme }: { theme: 'light' | 'dark' }) => { return generateAlertsDateArray(alertsData, currentTime); }, [alertsData, currentTime]); - const chartData: AlertsChartBar[][] = useMemo(() => { - if (!Array.isArray(alertsData) || alertsData.length === 0) return []; - return alertsData.map((alert) => createAlertsChartBars(alert)); - }, [alertsData]); + const { + chartData, + chartContainerHeight, + chartHeight, + }: { chartData: AlertsChartBar[][]; chartContainerHeight: number; chartHeight: number } = + useMemo(() => { + if (!Array.isArray(alertsData) || alertsData.length === 0) { + return { + chartData: [], + chartContainerHeight: DEFAULT_CHART_CONTAINER_HEIGHT, + chartHeight: DEFAULT_CHART_HEIGHT, + }; + } + const chartData = alertsData.map((alert) => createAlertsChartBars(alert)); + if (chartData.length < 5) { + return { + chartData, + chartContainerHeight: DEFAULT_CHART_CONTAINER_HEIGHT, + chartHeight: DEFAULT_CHART_HEIGHT, + }; + } - useEffect(() => { - // eslint-disable-next-line react-hooks/set-state-in-effect - setChartContainerHeight(chartData?.length < 5 ? 300 : chartData?.length * 55); - setChartHeight(chartData?.length < 5 ? 250 : chartData?.length * 55); - }, [chartData]); + return { + chartData, + chartContainerHeight: chartData.length * 55, + chartHeight: chartData.length * 55, + }; + }, [alertsData]); const selectedIncidentIsVisible = useMemo(() => { return filteredData.some( @@ -100,8 +119,6 @@ const AlertsChart = ({ theme }: { theme: 'light' | 'dark' }) => { } }, []); useEffect(() => { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore const observer = getResizeObserver(containerRef.current, handleResize); handleResize(); return () => observer(); diff --git a/web/src/components/Incidents/IncidentsChart/IncidentsChart.tsx b/web/src/components/Incidents/IncidentsChart/IncidentsChart.tsx index 2d7e456b8..b4153ded4 100644 --- a/web/src/components/Incidents/IncidentsChart/IncidentsChart.tsx +++ b/web/src/components/Incidents/IncidentsChart/IncidentsChart.tsx @@ -38,6 +38,7 @@ import { import { dateTimeFormatter, timeFormatter } from '../../console/utils/datetime'; import { useTranslation } from 'react-i18next'; import { DataTestIDs } from '../../data-test'; +import { DEFAULT_CHART_CONTAINER_HEIGHT, DEFAULT_CHART_HEIGHT } from '../AlertsChart/AlertsChart'; /** * Processes component list: moves "Others" to end and limits display to 3 components @@ -73,8 +74,6 @@ const IncidentsChart = ({ lastRefreshTime: number | null; }) => { const [isLoading, setIsLoading] = useState(true); - const [chartContainerHeight, setChartContainerHeight] = useState(); - const [chartHeight, setChartHeight] = useState(); const dateValues = useMemo( () => generateDateArray(chartDays, currentTime), [chartDays, currentTime], @@ -82,8 +81,14 @@ const IncidentsChart = ({ const { t, i18n } = useTranslation(process.env.I18N_NAMESPACE); - const chartData = useMemo(() => { - if (!Array.isArray(incidentsData) || incidentsData.length === 0) return []; + const { chartData, chartContainerHeight, chartHeight } = useMemo(() => { + if (!Array.isArray(incidentsData) || incidentsData.length === 0) { + return { + chartData: [], + chartContainerHeight: DEFAULT_CHART_CONTAINER_HEIGHT, + chartHeight: DEFAULT_CHART_HEIGHT, + }; + } const filteredIncidents = selectedGroupId ? incidentsData.filter((incident) => incident.group_id === selectedGroupId) @@ -96,7 +101,20 @@ const IncidentsChart = ({ chartBars.sort((a, b) => a[0].x - b[0].x); // Reassign consecutive x values to eliminate gaps between bars - return chartBars.map((bars, index) => bars.map((bar) => ({ ...bar, x: index + 1 }))); + const chartData = chartBars.map((bars, index) => bars.map((bar) => ({ ...bar, x: index + 1 }))); + if (chartData.length < 5) { + return { + chartData, + chartContainerHeight: DEFAULT_CHART_CONTAINER_HEIGHT, + chartHeight: DEFAULT_CHART_HEIGHT, + }; + } + + return { + chartData, + chartContainerHeight: chartData.length * 60, + chartHeight: chartData.length * 55, + }; }, [incidentsData, dateValues, selectedGroupId]); useEffect(() => { @@ -104,12 +122,6 @@ const IncidentsChart = ({ setIsLoading(false); }, [incidentsData]); - useEffect(() => { - // eslint-disable-next-line react-hooks/set-state-in-effect - setChartContainerHeight(chartData?.length < 5 ? 300 : chartData?.length * 60); - setChartHeight(chartData?.length < 5 ? 250 : chartData?.length * 55); - }, [chartData]); - const [width, setWidth] = useState(0); const containerRef = useRef(null); diff --git a/web/src/components/console/public/components/autocomplete.tsx b/web/src/components/console/public/components/autocomplete.tsx index 0b39ab5c7..c84c521fe 100644 --- a/web/src/components/console/public/components/autocomplete.tsx +++ b/web/src/components/console/public/components/autocomplete.tsx @@ -1,5 +1,5 @@ import type { ComponentProps, FC, SetStateAction, Dispatch, FormEvent } from 'react'; -import { useState, useEffect } from 'react'; +import { useMemo } from 'react'; import { css } from '@patternfly/react-styles'; import * as _ from 'lodash-es'; @@ -74,7 +74,6 @@ type AutocompleteInputProps = { }; const AutocompleteInput: FC = (props) => { - const [suggestions, setSuggestions] = useState(); const { visible, setVisible, ref } = useDocumentListener(suggestionBoxKeyHandler); const { textValue, @@ -110,18 +109,19 @@ const AutocompleteInput: FC = (props) => { setTextValue(input); }; - useEffect(() => { - if (textValue && visible && showSuggestions) { - const processed = labelParser(data, labelPath); - // User input without whitespace - const processedText = textValue.trim().replace(/\s*=\s*/, '='); - const maxSuggestions = suggestionCount ?? MAX_SUGGESTIONS; - const filtered = [...processed] - .filter((item) => fuzzyCaseInsensitive(processedText, item)) - .slice(0, maxSuggestions); - // eslint-disable-next-line react-hooks/set-state-in-effect - setSuggestions(filtered); + const suggestions = useMemo(() => { + if (!textValue || !visible || !showSuggestions) { + return []; } + + const processed = labelParser(data, labelPath); + // User input without whitespace + const processedText = textValue.trim().replace(/\s*=\s*/, '='); + const maxSuggestions = suggestionCount ?? MAX_SUGGESTIONS; + const filtered = [...processed] + .filter((item) => fuzzyCaseInsensitive(processedText, item)) + .slice(0, maxSuggestions); + return filtered; }, [visible, textValue, showSuggestions, data, labelPath, suggestionCount]); return (