Skip to content

Commit f796449

Browse files
authored
fix(ui): skip history.push on initial page load. Fixes #13940 (#13995)
Signed-off-by: Tianchu Zhao <[email protected]>
1 parent 43c6abd commit f796449

16 files changed

+197
-139
lines changed

ui/src/cron-workflows/cron-workflow-details.tsx

+16-13
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {NotificationType} from 'argo-ui/src/components/notifications/notificatio
22
import {Page} from 'argo-ui/src/components/page/page';
33
import {SlidingPanel} from 'argo-ui/src/components/sliding-panel/sliding-panel';
44
import * as React from 'react';
5-
import {useContext, useEffect, useState} from 'react';
5+
import {useContext, useEffect, useRef, useState} from 'react';
66
import {RouteComponentProps} from 'react-router';
77

88
import {uiUrl} from '../shared/base';
@@ -29,6 +29,7 @@ export function CronWorkflowDetails({match, location, history}: RouteComponentPr
2929
const {navigation, notifications, popup} = useContext(Context);
3030
const queryParams = new URLSearchParams(location.search);
3131

32+
const isFirstRender = useRef(true);
3233
const [namespace] = useState(match.params.namespace);
3334
const [name] = useState(match.params.name);
3435
const [sidePanel, setSidePanel] = useState(queryParams.get('sidePanel'));
@@ -47,18 +48,20 @@ export function CronWorkflowDetails({match, location, history}: RouteComponentPr
4748
[history]
4849
);
4950

50-
useEffect(
51-
() =>
52-
history.push(
53-
historyUrl('cron-workflows/{namespace}/{name}', {
54-
namespace,
55-
name,
56-
sidePanel,
57-
tab
58-
})
59-
),
60-
[namespace, name, sidePanel, tab]
61-
);
51+
useEffect(() => {
52+
if (isFirstRender.current) {
53+
isFirstRender.current = false;
54+
return;
55+
}
56+
history.push(
57+
historyUrl('cron-workflows/{namespace}/{name}', {
58+
namespace,
59+
name,
60+
sidePanel,
61+
tab
62+
})
63+
);
64+
}, [namespace, name, sidePanel, tab]);
6265

6366
useEffect(() => {
6467
services.cronWorkflows

ui/src/cron-workflows/cron-workflow-list.tsx

+14-11
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {Page} from 'argo-ui/src/components/page/page';
22
import {SlidingPanel} from 'argo-ui/src/components/sliding-panel/sliding-panel';
33
import * as React from 'react';
4-
import {useContext, useEffect, useState} from 'react';
4+
import {useContext, useEffect, useRef, useState} from 'react';
55
import {RouteComponentProps} from 'react-router-dom';
66

77
import {uiUrl} from '../shared/base';
@@ -33,6 +33,7 @@ export function CronWorkflowList({match, location, history}: RouteComponentProps
3333
const {navigation} = useContext(Context);
3434

3535
// state for URL, query, and label parameters
36+
const isFirstRender = useRef(true);
3637
const [namespace, setNamespace] = useState<string>(nsUtils.getNamespace(match.params.namespace) || '');
3738
const [sidePanel, setSidePanel] = useState(queryParams.get('sidePanel') === 'true');
3839
const [labels, setLabels] = useState<string[]>([]);
@@ -49,16 +50,18 @@ export function CronWorkflowList({match, location, history}: RouteComponentProps
4950
);
5051

5152
// save history
52-
useEffect(
53-
() =>
54-
history.push(
55-
historyUrl('cron-workflows' + (nsUtils.getManagedNamespace() ? '' : '/{namespace}'), {
56-
namespace,
57-
sidePanel
58-
})
59-
),
60-
[namespace, sidePanel]
61-
);
53+
useEffect(() => {
54+
if (isFirstRender.current) {
55+
isFirstRender.current = false;
56+
return;
57+
}
58+
history.push(
59+
historyUrl('cron-workflows' + (nsUtils.getManagedNamespace() ? '' : '/{namespace}'), {
60+
namespace,
61+
sidePanel
62+
})
63+
);
64+
}, [namespace, sidePanel]);
6265

6366
// internal state
6467
const [error, setError] = useState<Error>();

ui/src/event-flow/event-flow-page.tsx

+18-15
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {Page} from 'argo-ui/src/components/page/page';
22
import {SlidingPanel} from 'argo-ui/src/components/sliding-panel/sliding-panel';
33
import {Tabs} from 'argo-ui/src/components/tabs/tabs';
4-
import {useContext, useEffect, useState} from 'react';
4+
import {useContext, useEffect, useRef, useState} from 'react';
55
import * as React from 'react';
66
import {RouteComponentProps} from 'react-router-dom';
77
import {Observable} from 'rxjs';
@@ -43,6 +43,7 @@ export function EventFlowPage({history, location, match}: RouteComponentProps<an
4343
const queryParams = new URLSearchParams(location.search);
4444

4545
// state for URL and query parameters
46+
const isFirstRender = useRef(true);
4647
const [namespace, setNamespace] = useState(nsUtils.getNamespace(match.params.namespace) || '');
4748
const [showFlow, setShowFlow] = useState(queryParams.get('showFlow') === 'true');
4849
const [showWorkflows, setShowWorkflows] = useState(queryParams.get('showWorkflows') !== 'false');
@@ -61,20 +62,22 @@ export function EventFlowPage({history, location, match}: RouteComponentProps<an
6162
[history]
6263
);
6364

64-
useEffect(
65-
() =>
66-
history.push(
67-
historyUrl('event-flow' + (nsUtils.getManagedNamespace() ? '' : '/{namespace}'), {
68-
namespace,
69-
showFlow,
70-
showWorkflows,
71-
expanded,
72-
selectedNode,
73-
tab
74-
})
75-
),
76-
[namespace, showFlow, showWorkflows, expanded, expanded, tab]
77-
);
65+
useEffect(() => {
66+
if (isFirstRender.current) {
67+
isFirstRender.current = false;
68+
return;
69+
}
70+
history.push(
71+
historyUrl('event-flow' + (nsUtils.getManagedNamespace() ? '' : '/{namespace}'), {
72+
namespace,
73+
showFlow,
74+
showWorkflows,
75+
expanded,
76+
selectedNode,
77+
tab
78+
})
79+
);
80+
}, [namespace, showFlow, showWorkflows, expanded, expanded, tab]);
7881

7982
// internal state
8083
const [error, setError] = useState<Error>();

ui/src/event-sources/event-source-details.tsx

+16-13
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {Page} from 'argo-ui/src/components/page/page';
33
import {SlidingPanel} from 'argo-ui/src/components/sliding-panel/sliding-panel';
44
import {Tabs} from 'argo-ui/src/components/tabs/tabs';
55
import * as React from 'react';
6-
import {useContext, useEffect, useState} from 'react';
6+
import {useContext, useEffect, useRef, useState} from 'react';
77
import {RouteComponentProps} from 'react-router';
88

99
import {ID} from '../event-flow/id';
@@ -27,6 +27,7 @@ export function EventSourceDetails({history, location, match}: RouteComponentPro
2727
const queryParams = new URLSearchParams(location.search);
2828

2929
// state for URL and query parameters
30+
const isFirstRender = useRef(true);
3031
const namespace = match.params.namespace;
3132
const name = match.params.name;
3233
const [tab, setTab] = useState<string>(queryParams.get('tab'));
@@ -40,18 +41,20 @@ export function EventSourceDetails({history, location, match}: RouteComponentPro
4041
[history]
4142
);
4243

43-
useEffect(
44-
() =>
45-
history.push(
46-
historyUrl('event-sources/{namespace}/{name}', {
47-
namespace,
48-
name,
49-
tab,
50-
selectedNode
51-
})
52-
),
53-
[namespace, name, tab, selectedNode]
54-
);
44+
useEffect(() => {
45+
if (isFirstRender.current) {
46+
isFirstRender.current = false;
47+
return;
48+
}
49+
history.push(
50+
historyUrl('event-sources/{namespace}/{name}', {
51+
namespace,
52+
name,
53+
tab,
54+
selectedNode
55+
})
56+
);
57+
}, [namespace, name, tab, selectedNode]);
5558

5659
const [error, setError] = useState<Error>();
5760
const {object: eventSource, setObject: setEventSource, resetObject: resetEventSource, serialization, edited, lang, setLang} = useEditableObject<EventSource>();

ui/src/event-sources/event-source-list.tsx

+16-13
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {SlidingPanel} from 'argo-ui/src/components/sliding-panel/sliding-panel';
33
import {Tabs} from 'argo-ui/src/components/tabs/tabs';
44
import classNames from 'classnames';
55
import * as React from 'react';
6-
import {useContext, useEffect, useState} from 'react';
6+
import {useContext, useEffect, useRef, useState} from 'react';
77
import {Link, RouteComponentProps} from 'react-router-dom';
88

99
import {ID} from '../event-flow/id';
@@ -36,6 +36,7 @@ export function EventSourceList({match, location, history}: RouteComponentProps<
3636
const {navigation} = useContext(Context);
3737

3838
// state for URL and query parameters
39+
const isFirstRender = useRef(true);
3940
const [namespace, setNamespace] = useState(nsUtils.getNamespace(match.params.namespace) || '');
4041
const [sidePanel, setSidePanel] = useState(queryParams.get('sidePanel') === 'true');
4142
const [selectedNode, setSelectedNode] = useState<Node>(queryParams.get('selectedNode'));
@@ -50,18 +51,20 @@ export function EventSourceList({match, location, history}: RouteComponentProps<
5051
[history]
5152
);
5253

53-
useEffect(
54-
() =>
55-
history.push(
56-
historyUrl('event-sources' + (nsUtils.getManagedNamespace() ? '' : '/{namespace}'), {
57-
namespace,
58-
sidePanel,
59-
selectedNode,
60-
tab
61-
})
62-
),
63-
[namespace, sidePanel, selectedNode, tab]
64-
);
54+
useEffect(() => {
55+
if (isFirstRender.current) {
56+
isFirstRender.current = false;
57+
return;
58+
}
59+
history.push(
60+
historyUrl('event-sources' + (nsUtils.getManagedNamespace() ? '' : '/{namespace}'), {
61+
namespace,
62+
sidePanel,
63+
selectedNode,
64+
tab
65+
})
66+
);
67+
}, [namespace, sidePanel, selectedNode, tab]);
6568

6669
// internal state
6770
const [error, setError] = useState<Error>();

ui/src/plugins/plugin-list.tsx

+13-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {Page} from 'argo-ui/src/components/page/page';
22
import * as React from 'react';
3-
import {useEffect, useState} from 'react';
3+
import {useEffect, useRef, useState} from 'react';
44
import {RouteComponentProps} from 'react-router-dom';
55

66
import {uiUrl} from '../shared/base';
@@ -11,16 +11,19 @@ import {useCollectEvent} from '../shared/use-collect-event';
1111

1212
export function PluginList({match, history}: RouteComponentProps<any>) {
1313
// state for URL and query parameters
14+
const isFirstRender = useRef(true);
1415
const [namespace] = useState(nsUtils.getNamespace(match.params.namespace) || '');
15-
useEffect(
16-
() =>
17-
history.push(
18-
historyUrl('plugins' + (nsUtils.getManagedNamespace() ? '' : '/{namespace}'), {
19-
namespace
20-
})
21-
),
22-
[namespace]
23-
);
16+
useEffect(() => {
17+
if (isFirstRender.current) {
18+
isFirstRender.current = false;
19+
return;
20+
}
21+
history.push(
22+
historyUrl('plugins' + (nsUtils.getManagedNamespace() ? '' : '/{namespace}'), {
23+
namespace
24+
})
25+
);
26+
}, [namespace]);
2427
useCollectEvent('openedPlugins');
2528

2629
return (

ui/src/reports/reports.tsx

+6-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {ChartOptions} from 'chart.js';
44
import 'chartjs-plugin-annotation';
55

66
import * as React from 'react';
7-
import {useContext, useEffect, useState} from 'react';
7+
import {useContext, useEffect, useRef, useState} from 'react';
88
import {Bar, ChartData} from 'react-chartjs-2';
99
import {RouteComponentProps} from 'react-router-dom';
1010

@@ -33,6 +33,7 @@ export function Reports({match, location, history}: RouteComponentProps<any>) {
3333
const {navigation} = useContext(Context);
3434

3535
// state for URL, query, and label parameters
36+
const isFirstRender = useRef(true);
3637
const [namespace, setNamespace] = useState<string>(nsUtils.getNamespace(match.params.namespace) || '');
3738
const [labels, setLabels] = useState((queryParams.get('labels') || '').split(',').filter(v => v !== ''));
3839
// internal state
@@ -41,6 +42,10 @@ export function Reports({match, location, history}: RouteComponentProps<any>) {
4142

4243
// save history
4344
useEffect(() => {
45+
if (isFirstRender.current) {
46+
isFirstRender.current = false;
47+
return;
48+
}
4449
history.push(historyUrl('reports' + (nsUtils.getManagedNamespace() ? '' : '/{namespace}'), {namespace, labels: labels.join(',')}));
4550
}, [namespace, labels]);
4651

ui/src/sensors/sensor-details.tsx

+16-13
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {NotificationType} from 'argo-ui/src/components/notifications/notifications';
22
import {Page} from 'argo-ui/src/components/page/page';
33
import * as React from 'react';
4-
import {useContext, useEffect, useState} from 'react';
4+
import {useContext, useEffect, useRef, useState} from 'react';
55
import {RouteComponentProps} from 'react-router';
66

77
import {ID} from '../event-flow/id';
@@ -23,6 +23,7 @@ import '../workflows/components/workflow-details/workflow-details.scss';
2323

2424
export function SensorDetails({match, location, history}: RouteComponentProps<any>) {
2525
// boiler-plate
26+
const isFirstRender = useRef(true);
2627
const {navigation, notifications, popup} = useContext(Context);
2728
const queryParams = new URLSearchParams(location.search);
2829

@@ -42,18 +43,20 @@ export function SensorDetails({match, location, history}: RouteComponentProps<an
4243
[history]
4344
);
4445

45-
useEffect(
46-
() =>
47-
history.push(
48-
historyUrl('sensors/{namespace}/{name}', {
49-
namespace,
50-
name,
51-
tab,
52-
selectedLogNode
53-
})
54-
),
55-
[namespace, name, tab, selectedLogNode]
56-
);
46+
useEffect(() => {
47+
if (isFirstRender.current) {
48+
isFirstRender.current = false;
49+
return;
50+
}
51+
history.push(
52+
historyUrl('sensors/{namespace}/{name}', {
53+
namespace,
54+
name,
55+
tab,
56+
selectedLogNode
57+
})
58+
);
59+
}, [namespace, name, tab, selectedLogNode]);
5760

5861
useEffect(() => {
5962
services.sensor

0 commit comments

Comments
 (0)