Skip to content

Commit

Permalink
Add useWeakSharedState
Browse files Browse the repository at this point in the history
  • Loading branch information
tujoworker committed Dec 13, 2024
1 parent d1dd702 commit 1bc1e49
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
createSharedState,
SharedStateId,
createReferenceKey,
useWeakSharedState,
} from '../useSharedState'
import { createContext } from 'react'

Expand Down Expand Up @@ -110,30 +111,6 @@ describe('useSharedState', () => {
expect(result.current.data).toEqual({ test: 'initial' })
})

it('should delete the shared state when all components have been unmounted', () => {
const identifier = {}

const { unmount: unmountA } = renderHook(() =>
useSharedState(identifier, { test: 'initial' })
)
const { unmount: unmountB } = renderHook(() =>
useSharedState(identifier)
)

const getStateOf = (identifier) => {
return createSharedState(identifier).get()
}

expect(getStateOf(identifier)).toEqual({ test: 'initial' })
expect(getStateOf(identifier)).toEqual({ test: 'initial' })

unmountA()
unmountB()

expect(getStateOf(identifier)).toEqual(undefined)
expect(getStateOf(identifier)).toEqual(undefined)
})

it('should return undefined data when no ID is given', () => {
const { result } = renderHook(() =>
useSharedState(null, { test: 'initial' })
Expand Down Expand Up @@ -276,6 +253,56 @@ describe('useSharedState', () => {
})
})

describe('useWeakSharedState', () => {
it('should delete the shared state when all components have been unmounted', () => {
const identifier = {}

const { unmount: unmountA } = renderHook(() =>
useWeakSharedState(identifier, { test: 'initial' })
)
const { unmount: unmountB } = renderHook(() =>
useWeakSharedState(identifier)
)

const getStateOf = (identifier) => {
return createSharedState(identifier).get()
}

expect(getStateOf(identifier)).toEqual({ test: 'initial' })
expect(getStateOf(identifier)).toEqual({ test: 'initial' })

unmountA()
unmountB()

expect(getStateOf(identifier)).toEqual(undefined)
expect(getStateOf(identifier)).toEqual(undefined)
})

it('when not using weak, should not delete the shared state when all components have been unmounted', () => {
const identifier = {}

const { unmount: unmountA } = renderHook(() =>
useSharedState(identifier, { test: 'initial' })
)
const { unmount: unmountB } = renderHook(() =>
useSharedState(identifier)
)

const getStateOf = (identifier) => {
return createSharedState(identifier).get()
}

expect(getStateOf(identifier)).toEqual({ test: 'initial' })
expect(getStateOf(identifier)).toEqual({ test: 'initial' })

unmountA()
unmountB()

expect(getStateOf(identifier)).toEqual({ test: 'initial' })
expect(getStateOf(identifier)).toEqual({ test: 'initial' })
})
})

describe('createReferenceKey', () => {
it('should return the same object for the same references', () => {
const ref1 = {}
Expand Down
7 changes: 5 additions & 2 deletions packages/dnb-eufemia/src/shared/helpers/useSharedState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export type SharedStateId =
| Record<string, unknown>

/**
* Custom hook that provides shared state functionality.
* The shared state will be deleted when all components have been unmounted.
*/
export function useWeakSharedState<
Data,
Expand All @@ -45,7 +45,10 @@ export function useSharedState<Data>(
/** Optional callback function to be called when the shared state is set from another instance/component. */
onChange = null,
/** Optional configuration options. */
{ weak = false } = {}
{
/** When set to `true`, the shared state will be deleted when all components have been unmounted. */
weak = false,
} = {}
) {
const [, forceUpdate] = useReducer(() => ({}), {})
const hasMountedRef = useMounted()
Expand Down

0 comments on commit 1bc1e49

Please sign in to comment.