|
1 | | -const { useState, useEffect, useRef, useCallback } = React; |
| 1 | +const { useState, useEffect, useRef, useCallback, useMemo } = React; |
2 | 2 |
|
3 | 3 | // Determine the directory where the plugin's files are installed. When running |
4 | 4 | // inside Cockpit, `window.cockpit.manifest.path` points to the plugin root |
@@ -50,8 +50,10 @@ function getYearPeriod(year = new Date().getFullYear()) { |
50 | 50 | function useBillingData(period) { |
51 | 51 | const [data, setData] = useState(null); |
52 | 52 | const [error, setError] = useState(null); |
| 53 | + const requestIdRef = useRef(0); |
53 | 54 |
|
54 | 55 | const load = useCallback(async () => { |
| 56 | + const id = ++requestIdRef.current; |
55 | 57 | try { |
56 | 58 | let json; |
57 | 59 | if (window.cockpit && window.cockpit.spawn) { |
@@ -80,11 +82,15 @@ function useBillingData(period) { |
80 | 82 | if (!resp.ok) throw new Error('Failed to fetch billing data'); |
81 | 83 | json = await resp.json(); |
82 | 84 | } |
83 | | - setData(json); |
84 | | - setError(null); |
| 85 | + if (requestIdRef.current === id) { |
| 86 | + setData(json); |
| 87 | + setError(null); |
| 88 | + } |
85 | 89 | } catch (e) { |
86 | 90 | console.error(e); |
87 | | - setError(e.message || String(e)); |
| 91 | + if (requestIdRef.current === id) { |
| 92 | + setError(e.message || String(e)); |
| 93 | + } |
88 | 94 | } |
89 | 95 | }, [period]); |
90 | 96 |
|
@@ -1138,12 +1144,13 @@ function Rates({ onRatesUpdated }) { |
1138 | 1144 | function App() { |
1139 | 1145 | const [view, setView] = useState('year'); |
1140 | 1146 | const now = new Date(); |
1141 | | - const defaultMonth = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart( |
| 1147 | + const currentYear = now.getFullYear(); |
| 1148 | + const defaultMonth = `${currentYear}-${String(now.getMonth() + 1).padStart( |
1142 | 1149 | 2, |
1143 | 1150 | '0' |
1144 | 1151 | )}`; |
1145 | 1152 | const [month, setMonth] = useState(defaultMonth); |
1146 | | - const yearPeriod = getYearPeriod(now.getFullYear()); |
| 1153 | + const yearPeriod = useMemo(() => getYearPeriod(currentYear), [currentYear]); |
1147 | 1154 | const period = view === 'year' ? yearPeriod : month; |
1148 | 1155 | const { data, error, reload } = useBillingData(period); |
1149 | 1156 | const [showErrorDetails, setShowErrorDetails] = useState(false); |
|
0 commit comments