fix(ui): remove state updates on unmounted components

This commit is contained in:
sylenien 2022-05-17 10:12:11 +02:00 committed by Delirium
parent cba53fa284
commit 33ff7914be
3 changed files with 30 additions and 11 deletions

View file

@ -1,4 +1,4 @@
import React, { useState, useRef, useEffect } from 'react';
import React, { useState, useRef, useEffect, useCallback } from 'react';
import CustomMetriLineChart from 'App/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetriLineChart';
import CustomMetricPercentage from 'App/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPercentage';
import CustomMetricTable from 'App/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTable';
@ -9,8 +9,10 @@ import { Loader } from 'UI';
import { useStore } from 'App/mstore';
import WidgetPredefinedChart from '../WidgetPredefinedChart';
import CustomMetricOverviewChart from 'App/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricOverviewChart';
import { getStartAndEndTimestampsByDensity } from 'Types/dashboard/helper';
import { getStartAndEndTimestampsByDensity } from 'Types/dashboard/helper';
import { debounce } from 'App/utils';
import useIsMounted from 'App/hooks/useIsMounted'
interface Props {
metric: any;
isWidget?: boolean
@ -24,12 +26,12 @@ function WidgetChart(props: Props) {
const colors = Styles.customMetricColors;
const [loading, setLoading] = useState(true)
const isOverviewWidget = metric.metricType === 'predefined' && metric.viewType === 'overview';
const params = { density: isOverviewWidget ? 7 : 70 }
const params = { density: isOverviewWidget ? 7 : 70 }
const metricParams = { ...params }
const prevMetricRef = useRef<any>();
const isMounted = useIsMounted();
const [data, setData] = useState<any>(metric.data);
const isTableWidget = metric.metricType === 'table' && metric.viewType === 'table';
const isPieChart = metric.metricType === 'table' && metric.viewType === 'pieChart';
@ -57,16 +59,16 @@ function WidgetChart(props: Props) {
const depsString = JSON.stringify(_metric.series);
const fetchMetricChartData = (metric, payload, isWidget) => {
if (!isMounted()) return;
setLoading(true)
dashboardStore.fetchMetricChartData(metric, payload, isWidget).then((res: any) => {
setData(res);
if (isMounted()) setData(res);
}).finally(() => {
setLoading(false);
});
}
const debounceRequest: any = React.useCallback(debounce(fetchMetricChartData, 500), []);
useEffect(() => {
if (prevMetricRef.current && prevMetricRef.current.name !== metric.name) {
@ -137,4 +139,4 @@ function WidgetChart(props: Props) {
));
}
export default observer(WidgetChart);
export default observer(WidgetChart);

View file

@ -6,13 +6,15 @@ import SessionItem from 'Shared/SessionItem';
import { observer, useObserver } from 'mobx-react-lite';
import { DateTime } from 'luxon';
import { debounce } from 'App/utils';
import useIsMounted from 'App/hooks/useIsMounted'
interface Props {
className?: string;
}
function WidgetSessions(props: Props) {
const { className = '' } = props;
const [data, setData] = useState<any>([]);
const isMounted = useIsMounted()
const [loading, setLoading] = useState(false);
const [seriesOptions, setSeriesOptions] = useState([
{ text: 'All', value: 'all' },
@ -34,6 +36,7 @@ function WidgetSessions(props: Props) {
}, [data]);
const fetchSessions = (metricId, filter) => {
if (!isMounted()) return;
setLoading(true)
widget.fetchSessions(metricId, filter).then(res => {
setData(res)
@ -41,7 +44,7 @@ function WidgetSessions(props: Props) {
setLoading(false)
});
}
const filteredSessions = getListSessionsBySeries(data, activeSeries);
const { dashboardStore, metricStore } = useStore();
const filter = useObserver(() => dashboardStore.drillDownFilter);
@ -126,4 +129,4 @@ const getListSessionsBySeries = (data, seriesId) => {
return arr;
}
export default observer(WidgetSessions);
export default observer(WidgetSessions);

View file

@ -0,0 +1,14 @@
import { useRef, useEffect, useCallback } from 'react'
export default function useIsMounted(): () => boolean {
const ref = useRef(false);
useEffect(() => {
ref.current = true;
return () => {
ref.current = false;
};
}, []);
return useCallback(() => ref.current, [ref]);
}