@oslokommune/punkt-react
Version:
React komponentbibliotek til Punkt, et designsystem laget av Oslo Origo
52 lines (44 loc) • 1.77 kB
text/typescript
import { useCallback, useEffect, useState } from 'react'
import { TFileId, TQueueItemOperation } from '../types'
export const useOperationState = (queueItemOperations: TQueueItemOperation[]) => {
const [activatedIds, setActivatedIds] = useState<Record<TFileId, string>>({})
// If an operation is removed from the list while still referenced as "activated",
// the stored id would re-activate a freshly-added operation with the same id
// (e.g. an extension re-mounted). Drop any stale entries on list changes so the
// activation state can never refer to an operation that no longer exists.
useEffect(() => {
setActivatedIds((prev) => {
const validIds = new Set(queueItemOperations.map((op) => op.id))
let changed = false
const next: Record<TFileId, string> = {}
for (const [fileId, opId] of Object.entries(prev)) {
if (validIds.has(opId)) {
next[fileId] = opId
} else {
changed = true
}
}
return changed ? next : prev
})
}, [queueItemOperations])
const getActivated = useCallback(
(fileId: TFileId): TQueueItemOperation | undefined => {
const id = activatedIds[fileId]
if (!id) return undefined
return queueItemOperations.find((op) => op.id === id)
},
[activatedIds, queueItemOperations],
)
const activate = useCallback((fileId: TFileId, operation: TQueueItemOperation) => {
setActivatedIds((prev) => ({ ...prev, [fileId]: operation.id }))
}, [])
const close = useCallback((fileId: TFileId) => {
setActivatedIds((prev) => {
if (!(fileId in prev)) return prev
const updated = { ...prev }
delete updated[fileId]
return updated
})
}, [])
return { getActivated, activate, close }
}