1
1
import { useLayoutEffect , useState } from 'react'
2
- import { FacetProp , isFacet , Value , NoValue } from '../types'
2
+ import { FacetProp , isFacet , Value , NoValue , EqualityCheck , NO_VALUE } from '../types'
3
+ import { defaultEqualityCheck } from '../equalityChecks'
3
4
4
5
/**
5
6
* Hook that allows consuming values from a Facet
6
7
* It acts as a regular react state, triggering a re-render of the component
7
8
*
8
9
* @param facet
9
10
*/
10
- export function useFacetUnwrap < T extends Value > ( prop : FacetProp < T > ) : T | NoValue {
11
+ export function useFacetUnwrap < T extends Value > (
12
+ prop : FacetProp < T > ,
13
+ equalityCheck : EqualityCheck < T > = defaultEqualityCheck ,
14
+ ) : T | NoValue {
11
15
const [ state , setState ] = useState < { value : T | NoValue } > ( ( ) => {
12
16
if ( ! isFacet ( prop ) ) return { value : prop }
13
17
@@ -18,12 +22,17 @@ export function useFacetUnwrap<T extends Value>(prop: FacetProp<T>): T | NoValue
18
22
19
23
useLayoutEffect ( ( ) => {
20
24
if ( isFacet ( prop ) ) {
25
+ // Initialize the equalityCheck
26
+ const isEqual = equalityCheck ( )
27
+ const startValue = prop . get ( )
28
+ if ( startValue !== NO_VALUE ) {
29
+ isEqual ( startValue )
30
+ }
31
+
21
32
return prop . observe ( ( value ) => {
22
33
setState ( ( previousState ) => {
23
34
const { value : previousValue } = previousState
24
35
25
- const typeofValue = typeof previousValue
26
-
27
36
/**
28
37
* Performs this equality check locally to prevent triggering two consecutive renderings
29
38
* for facets that have immutable values (unfortunately we can't handle mutable values).
@@ -34,22 +43,32 @@ export function useFacetUnwrap<T extends Value>(prop: FacetProp<T>): T | NoValue
34
43
* - Once on initialization of the useState above
35
44
* - And another time on this observe initialization
36
45
*/
37
- if (
38
- ( typeofValue === 'number' ||
39
- typeofValue === 'string' ||
40
- typeofValue === 'boolean' ||
41
- value === undefined ||
42
- value === null ) &&
43
- value === previousValue
44
- ) {
46
+ if ( equalityCheck === defaultEqualityCheck ) {
47
+ const typeofValue = typeof previousValue
48
+
49
+ if (
50
+ ( typeofValue === 'number' ||
51
+ typeofValue === 'string' ||
52
+ typeofValue === 'boolean' ||
53
+ value === undefined ||
54
+ value === null ) &&
55
+ value === previousValue
56
+ ) {
57
+ return previousState
58
+ }
59
+
60
+ return { value }
61
+ }
62
+
63
+ if ( previousValue !== NO_VALUE && isEqual ( previousValue ) ) {
45
64
return previousState
46
65
}
47
66
48
67
return { value }
49
68
} )
50
69
} )
51
70
}
52
- } , [ prop ] )
71
+ } , [ prop , equalityCheck ] )
53
72
54
73
return isFacet ( prop ) ? state . value : prop
55
74
}
0 commit comments