Last active
May 17, 2024 22:16
-
-
Save karol-majewski/3ceb43ccfe0075e2d9ef7c7247e384d3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import createPersistedState from 'use-persisted-state'; | |
import { storage } from '../utilities/storage'; | |
import { hasElements, head, isDefined } from '@rhim/utils'; | |
const usePersistedEntityId = createPersistedState('some-entity-key', storage); | |
interface Entity { | |
id: UUID; | |
} | |
type Persistable = UUID | null; | |
/** | |
* @param entities The domain of possible values to select from | |
* @param initialValue A preferred initial value. Example use: obtain it from `URLSearchParams` | |
*/ | |
export function useSelectedEntityId(entities: Entity[], initialValue?: UUID): Persistable { | |
const [persistedEntityId, setPersistedEntityId] = usePersistedEntityId<Persistable>(initialValue ?? null); | |
const strategy = React.useCallback((entities: Entity[], persistedEntityId: Persistable): Persistable => { | |
const preferredEntity: Entity | undefined = entities.find((entity) => entity.id === persistedEntityId); | |
// True when the persisted entity ID matches the available entities. This is not always the case. | |
// For example, the entities might change in the meantime and so the persisted ID is outside the domain. | |
const hasPreferredEntity = isDefined(preferredEntity); | |
if (hasPreferredEntity) { | |
return preferredEntity.id; | |
} else if (hasElements(entities)) { | |
return head(entities).id; | |
} else { | |
return null; | |
} | |
}, []); | |
const currentValue = React.useMemo(() => { | |
return strategy(entities, persistedEntityId); | |
}, [entities, persistedEntityId, strategy]); | |
React.useEffect(() => { | |
const nextValue = strategy(entities, persistedEntityId); | |
if (currentValue !== nextValue) { | |
setPersistedEntityId(nextValue); | |
} | |
}, [currentValue, entities, persistedEntityId, setPersistedEntityId, strategy]) | |
return currentValue; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import createPersistedState from 'use-persisted-state'; | |
import { storage } from '../utilities/storage'; | |
import { hasElements, head, isDefined } from '@rhim/utils'; | |
const usePersistedEntityId = createPersistedState('some-entity-key', storage); | |
interface Entity { | |
id: UUID; | |
} | |
/** | |
* @param entities The domain of possible values to select from | |
* @param initialValue A preferred initial value. Example use: obtain it from `URLSearchParams` | |
*/ | |
export function useSelectedEntityId(entities: Entity[], initialValue?: UUID) { | |
const [persistedEntityId, setPersistedEntityId] = usePersistedEntityId<UUID | null>(initialValue ?? null); | |
// This is the value we're going to return. It's computed based on the persisted preference and the domain of available entities. | |
const entityId = React.useMemo(() => { | |
const preferredEntity: Entity | undefined = entities.find((entity) => entity.id === persistedEntityId); | |
// True when the persisted entity ID matches the available entities. This is not always the case. | |
// For example, the entities might change in the meantime and so the persisted ID is outside the domain. | |
const hasPreferredEntity = isDefined(preferredEntity); | |
if (hasPreferredEntity) { | |
return preferredEntity.id; | |
} else if (hasElements(entities)) { | |
return head(entities).id; | |
} else { | |
return null; | |
} | |
}, [entities, persistedEntityId]); | |
// Whenever either `entities` or `persistedEntityId` change, apply the same logic and persist the new value. | |
React.useEffect(() => { | |
const preferredEntity: Entity | undefined = entities.find((entity) => entity.id === persistedEntityId); | |
const hasPreferredEntity = isDefined(preferredEntity); | |
if (hasPreferredEntity) { | |
return; | |
} else if (hasElements(entities)) { | |
setPersistedEntityId(head(entities).id); | |
} else { | |
setPersistedEntityId(null); | |
} | |
}, [persistedEntityId, setPersistedEntityId, entities]); | |
return React.useMemo(() => { | |
return [entityId, setPersistedEntityId]; | |
}, [entityId, setPersistedEntityId]); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment