20
20
* SPDX-License-Identifier: Apache-2.0
21
21
********************************************************************************/
22
22
23
- import { useEffect , useState } from 'react' ;
23
+ import { useEffect , useState , useRef } from 'react' ;
24
24
import Box from '@mui/material/Box' ;
25
25
import Typography from '@mui/material/Typography' ;
26
26
import Paper from '@mui/material/Paper' ;
@@ -46,7 +46,7 @@ import { SerializedPart } from '../../../serialized-parts/types';
46
46
import { SerializedPartTwinRead } from '../../../serialized-parts/types/twin-types' ;
47
47
import { fetchSerializedParts } from '../../../serialized-parts/api' ;
48
48
import { createSerializedPartTwin , shareSerializedPartTwin , unshareSerializedPartTwin , deleteSerializedPart } from '../../../serialized-parts/api' ;
49
- import { fetchAllSerializedPartTwins } from '../../../serialized-parts/api' ;
49
+ import { fetchSerializedPartTwinsForCatalogPart } from '../../../serialized-parts/api' ;
50
50
import { PartType , StatusVariants } from '../../types/types' ;
51
51
import { SerializedPartStatusChip } from './SerializedPartStatusChip' ;
52
52
@@ -62,6 +62,9 @@ interface InstanceProductsTableProps {
62
62
}
63
63
64
64
export default function InstanceProductsTable ( { part, onAddClick } : Readonly < InstanceProductsTableProps > ) {
65
+ // Ref to prevent duplicate API calls in React StrictMode
66
+ const dataLoadedRef = useRef ( false ) ;
67
+
65
68
const [ rows , setRows ] = useState < SerializedPartWithStatus [ ] > ( [ ] ) ;
66
69
const [ twinCreatingId , setTwinCreatingId ] = useState < number | null > ( null ) ;
67
70
const [ twinSharingId , setTwinSharingId ] = useState < number | null > ( null ) ;
@@ -110,14 +113,22 @@ export default function InstanceProductsTable({ part, onAddClick }: Readonly<Ins
110
113
useEffect ( ( ) => {
111
114
if ( ! part ) {
112
115
setRows ( [ ] ) ;
116
+ dataLoadedRef . current = false ; // Reset ref when part changes
113
117
return ;
114
118
}
119
+
115
120
const loadData = async ( ) => {
121
+ // Prevent duplicate calls in React StrictMode
122
+ if ( dataLoadedRef . current ) {
123
+ return ;
124
+ }
125
+ dataLoadedRef . current = true ;
126
+
116
127
try {
117
128
// Fetch both serialized parts and twins
118
129
const [ serializedParts , twins ] = await Promise . all ( [
119
130
fetchSerializedParts ( part . manufacturerId , part . manufacturerPartId ) ,
120
- fetchAllSerializedPartTwins ( part . manufacturerId , part . manufacturerPartId )
131
+ fetchSerializedPartTwinsForCatalogPart ( part . manufacturerId , part . manufacturerPartId )
121
132
] ) ;
122
133
123
134
// Merge serialized parts with twin status
@@ -135,6 +146,8 @@ export default function InstanceProductsTable({ part, onAddClick }: Readonly<Ins
135
146
console . log ( 'Loaded instance products:' , rowsWithStatus ) ;
136
147
} catch ( error ) {
137
148
console . error ( "Error fetching instance products:" , error ) ;
149
+ // Reset ref on error so it can be retried
150
+ dataLoadedRef . current = false ;
138
151
}
139
152
} ;
140
153
@@ -163,7 +176,7 @@ export default function InstanceProductsTable({ part, onAddClick }: Readonly<Ins
163
176
// Refresh data after successful creation
164
177
const [ serializedParts , twins ] = await Promise . all ( [
165
178
fetchSerializedParts ( part . manufacturerId , part . manufacturerPartId ) ,
166
- fetchAllSerializedPartTwins ( part . manufacturerId , part . manufacturerPartId )
179
+ fetchSerializedPartTwinsForCatalogPart ( part . manufacturerId , part . manufacturerPartId )
167
180
] ) ;
168
181
169
182
const rowsWithStatus = serializedParts . map ( ( serializedPart , index ) => {
@@ -214,7 +227,7 @@ export default function InstanceProductsTable({ part, onAddClick }: Readonly<Ins
214
227
// Refresh data after successful share
215
228
const [ serializedParts , twins ] = await Promise . all ( [
216
229
fetchSerializedParts ( part . manufacturerId , part . manufacturerPartId ) ,
217
- fetchAllSerializedPartTwins ( part . manufacturerId , part . manufacturerPartId )
230
+ fetchSerializedPartTwinsForCatalogPart ( part . manufacturerId , part . manufacturerPartId )
218
231
] ) ;
219
232
220
233
const rowsWithStatus = serializedParts . map ( ( serializedPart , index ) => {
@@ -257,7 +270,7 @@ export default function InstanceProductsTable({ part, onAddClick }: Readonly<Ins
257
270
setTwinUnsharingId ( row . id ) ;
258
271
try {
259
272
// Find the twin to get the AAS ID
260
- const twins = await fetchAllSerializedPartTwins ( part . manufacturerId , part . manufacturerPartId ) ;
273
+ const twins = await fetchSerializedPartTwinsForCatalogPart ( part . manufacturerId , part . manufacturerPartId ) ;
261
274
const twin = twins . find (
262
275
( t ) => t . manufacturerId === row . manufacturerId &&
263
276
t . manufacturerPartId === row . manufacturerPartId &&
@@ -281,7 +294,7 @@ export default function InstanceProductsTable({ part, onAddClick }: Readonly<Ins
281
294
// Refresh data after successful unshare
282
295
const [ serializedParts , updatedTwins ] = await Promise . all ( [
283
296
fetchSerializedParts ( part . manufacturerId , part . manufacturerPartId ) ,
284
- fetchAllSerializedPartTwins ( part . manufacturerId , part . manufacturerPartId )
297
+ fetchSerializedPartTwinsForCatalogPart ( part . manufacturerId , part . manufacturerPartId )
285
298
] ) ;
286
299
287
300
const rowsWithStatus = serializedParts . map ( ( serializedPart , index ) => {
@@ -337,7 +350,7 @@ export default function InstanceProductsTable({ part, onAddClick }: Readonly<Ins
337
350
// Refresh data after successful deletion
338
351
const [ serializedParts , twins ] = await Promise . all ( [
339
352
fetchSerializedParts ( part . manufacturerId , part . manufacturerPartId ) ,
340
- fetchAllSerializedPartTwins ( part . manufacturerId , part . manufacturerPartId )
353
+ fetchSerializedPartTwinsForCatalogPart ( part . manufacturerId , part . manufacturerPartId )
341
354
] ) ;
342
355
343
356
const rowsWithStatus = serializedParts . map ( ( serializedPart , index ) => {
0 commit comments