|
1 |
| -import { useCallback, useRef } from 'react' |
| 1 | +import { useCallback, useLayoutEffect, useRef } from 'react' |
2 | 2 | import { NoValue } from '..'
|
3 | 3 | import { Facet, NO_VALUE, Option } from '../types'
|
4 |
| -import { useFacetEffect } from './useFacetEffect' |
| 4 | + |
| 5 | +// eslint-disable-next-line @typescript-eslint/no-explicit-any |
| 6 | +export function useFacetCallback<M, V, C extends (...args: any[]) => M | NoValue>( |
| 7 | + callback: (v: V) => C, |
| 8 | + dependencies: unknown[], |
| 9 | + facet: [Facet<V>], |
| 10 | +): C |
| 11 | + |
| 12 | +// eslint-disable-next-line @typescript-eslint/no-explicit-any |
| 13 | +export function useFacetCallback<M, V, V1, C extends (...args: any[]) => M | NoValue>( |
| 14 | + callback: (v: V, v1: V1) => C, |
| 15 | + dependencies: unknown[], |
| 16 | + facet: [Facet<V>, Facet<V1>], |
| 17 | +): C |
| 18 | + |
| 19 | +// eslint-disable-next-line @typescript-eslint/no-explicit-any |
| 20 | +export function useFacetCallback<M, V, V1, V2, C extends (...args: any[]) => M | NoValue>( |
| 21 | + callback: (v: V, v1: V1, v2: V2) => C, |
| 22 | + dependencies: unknown[], |
| 23 | + facet: [Facet<V>, Facet<V1>, Facet<V2>], |
| 24 | +): C |
| 25 | + |
| 26 | +// eslint-disable-next-line @typescript-eslint/no-explicit-any |
| 27 | +export function useFacetCallback<M, V, V1, V2, V3, C extends (...args: any[]) => M | NoValue>( |
| 28 | + callback: (v: V, v1: V1, v2: V2, v3: V3) => C, |
| 29 | + dependencies: unknown[], |
| 30 | + facet: [Facet<V>, Facet<V1>, Facet<V2>, Facet<V3>], |
| 31 | +): C |
| 32 | + |
| 33 | +// eslint-disable-next-line @typescript-eslint/no-explicit-any |
| 34 | +export function useFacetCallback<M, V, V1, V2, V3, V4, C extends (...args: any[]) => M | NoValue>( |
| 35 | + callback: (v: V, v1: V1, v2: V2, v3: V3, v4: V4) => C, |
| 36 | + dependencies: unknown[], |
| 37 | + facet: [Facet<V>, Facet<V1>, Facet<V2>, Facet<V3>, Facet<V4>], |
| 38 | +): C |
| 39 | + |
| 40 | +// eslint-disable-next-line @typescript-eslint/no-explicit-any |
| 41 | +export function useFacetCallback<M, V, V1, V2, V3, V4, V5, C extends (...args: any[]) => M | NoValue>( |
| 42 | + callback: (v: V, v1: V1, v2: V2, v3: V3, v4: V4, v5: V5) => C, |
| 43 | + dependencies: unknown[], |
| 44 | + facet: [Facet<V>, Facet<V1>, Facet<V2>, Facet<V3>, Facet<V4>, Facet<V5>], |
| 45 | +): C |
| 46 | + |
| 47 | +// eslint-disable-next-line @typescript-eslint/no-explicit-any |
| 48 | +export function useFacetCallback<M, V, V1, V2, V3, V4, V5, V6, C extends (...args: any[]) => M | NoValue>( |
| 49 | + callback: (v: V, v1: V1, v2: V2, v3: V3, v4: V4, v5: V5, v6: V6) => C, |
| 50 | + dependencies: unknown[], |
| 51 | + facet: [Facet<V>, Facet<V1>, Facet<V2>, Facet<V3>, Facet<V4>, Facet<V5>, Facet<V6>], |
| 52 | +): C |
| 53 | + |
| 54 | +// eslint-disable-next-line @typescript-eslint/no-explicit-any |
| 55 | +export function useFacetCallback<M, V, V1, V2, V3, V4, V5, V6, V7, C extends (...args: any[]) => M | NoValue>( |
| 56 | + callback: (v: V, v1: V1, v2: V2, v3: V3, v4: V4, v5: V5, v6: V6, v7: V7) => C, |
| 57 | + dependencies: unknown[], |
| 58 | + facet: [Facet<V>, Facet<V1>, Facet<V2>, Facet<V3>, Facet<V4>, Facet<V5>, Facet<V6>, Facet<V7>], |
| 59 | +): C |
| 60 | + |
| 61 | +// eslint-disable-next-line @typescript-eslint/no-explicit-any |
| 62 | +export function useFacetCallback<M, V, V1, V2, V3, V4, V5, V6, V7, V8, C extends (...args: any[]) => M | NoValue>( |
| 63 | + callback: (v: V, v1: V1, v2: V2, v3: V3, v4: V4, v5: V5, v6: V6, v7: V7, v8: V8) => C, |
| 64 | + dependencies: unknown[], |
| 65 | + facet: [Facet<V>, Facet<V1>, Facet<V2>, Facet<V3>, Facet<V4>, Facet<V5>, Facet<V6>, Facet<V7>, Facet<V8>], |
| 66 | +): C |
| 67 | + |
| 68 | +// eslint-disable-next-line @typescript-eslint/no-explicit-any |
| 69 | +export function useFacetCallback<M, V, V1, V2, V3, V4, V5, V6, V7, V8, V9, C extends (...args: any[]) => M | NoValue>( |
| 70 | + callback: (v: V, v1: V1, v2: V2, v3: V3, v4: V4, v5: V5, v6: V6, v7: V7, v8: V8, v9: V9) => C, |
| 71 | + dependencies: unknown[], |
| 72 | + facet: [Facet<V>, Facet<V1>, Facet<V2>, Facet<V3>, Facet<V4>, Facet<V5>, Facet<V6>, Facet<V7>, Facet<V8>, Facet<V9>], |
| 73 | +): C |
| 74 | + |
| 75 | +export function useFacetCallback< |
| 76 | + M, |
| 77 | + V, |
| 78 | + V1, |
| 79 | + V2, |
| 80 | + V3, |
| 81 | + V4, |
| 82 | + V5, |
| 83 | + V6, |
| 84 | + V7, |
| 85 | + V8, |
| 86 | + V9, |
| 87 | + V10, |
| 88 | + // eslint-disable-next-line @typescript-eslint/no-explicit-any |
| 89 | + C extends (...args: any[]) => M | NoValue, |
| 90 | +>( |
| 91 | + callback: (v: V, v1: V1, v2: V2, v3: V3, v4: V4, v5: V5, v6: V6, v7: V7, v8: V8, v9: V9, v10: V10) => C, |
| 92 | + dependencies: unknown[], |
| 93 | + facet: [ |
| 94 | + Facet<V>, |
| 95 | + Facet<V1>, |
| 96 | + Facet<V2>, |
| 97 | + Facet<V3>, |
| 98 | + Facet<V4>, |
| 99 | + Facet<V5>, |
| 100 | + Facet<V6>, |
| 101 | + Facet<V7>, |
| 102 | + Facet<V8>, |
| 103 | + Facet<V9>, |
| 104 | + Facet<V10>, |
| 105 | + ], |
| 106 | +): C |
5 | 107 |
|
6 | 108 | /**
|
7 | 109 | * Creates a callback that depends on the value of a facet.
|
8 | 110 | * Very similar to `useCallback` from `React`
|
9 | 111 | *
|
10 |
| - * @param callback function callback that receives the current facet value and the arguments passed to the callback |
11 |
| - * @param dependencies variable used by the map that are available in scope (similar as dependencies of useCallback) |
12 |
| - * @param facet facet that the callback listens to |
| 112 | + * @param callback function callback that receives the current facet values and the arguments passed to the callback |
| 113 | + * @param dependencies variable used by the callback that are available in scope (similar as dependencies of useCallback) |
| 114 | + * @param facets facets that the callback listens to |
13 | 115 | *
|
14 | 116 | * We pass the dependencies of the callback as the second argument so we can leverage the eslint-plugin-react-hooks option for additionalHooks.
|
15 | 117 | * Having this as the second argument allows the linter to work.
|
16 | 118 | */
|
17 |
| -export function useFacetCallback<V, T>( |
18 |
| - // eslint-disable-next-line @typescript-eslint/no-explicit-any |
19 |
| - callback: (value: V) => (...args: any[]) => T | NoValue, |
20 |
| - // eslint-disable-next-line @typescript-eslint/no-explicit-any |
21 |
| - dependencies: any[], |
22 |
| - facet: Facet<V>, |
23 |
| -) { |
24 |
| - const facetRef = useRef<Option<V>>(facet.get()) |
25 |
| - |
26 |
| - useFacetEffect( |
27 |
| - (value) => { |
28 |
| - facetRef.current = value |
29 |
| - }, |
30 |
| - [], |
31 |
| - facet, |
32 |
| - ) |
| 119 | +export function useFacetCallback<M>( |
| 120 | + callback: (...args: unknown[]) => (...args: unknown[]) => M | NoValue, |
| 121 | + dependencies: unknown[], |
| 122 | + facets: Facet<unknown>[], |
| 123 | +): (...args: unknown[]) => M | NoValue { |
| 124 | + const facetsRef = useRef<Option<unknown>[]>(facets.map(() => NO_VALUE)) |
| 125 | + |
| 126 | + useLayoutEffect(() => { |
| 127 | + const unsubscribes = facets.map((facet, index) => { |
| 128 | + return facet.observe((value) => { |
| 129 | + facetsRef.current[index] = value |
| 130 | + }) |
| 131 | + }) |
| 132 | + |
| 133 | + return () => { |
| 134 | + unsubscribes.forEach((unsubscribe) => unsubscribe()) |
| 135 | + } |
| 136 | + // We care about each individual facet and if any is a different reference |
| 137 | + // eslint-disable-next-line react-hooks/exhaustive-deps |
| 138 | + }, facets) |
| 139 | + |
| 140 | + // We care about each individual dependency and if any is a different reference |
33 | 141 | // eslint-disable-next-line react-hooks/exhaustive-deps
|
34 | 142 | const callbackMemoized = useCallback(callback, dependencies)
|
35 | 143 |
|
| 144 | + // eslint-disable-next-line react-hooks/exhaustive-deps |
36 | 145 | return useCallback(
|
37 |
| - // eslint-disable-next-line @typescript-eslint/no-explicit-any |
38 |
| - (...args: any[]): T | NoValue => { |
39 |
| - const value = facetRef.current |
| 146 | + (...args: unknown[]) => { |
| 147 | + const values = facetsRef.current |
40 | 148 |
|
41 |
| - if (value === NO_VALUE) return NO_VALUE |
| 149 | + for (const value of values) { |
| 150 | + if (value === NO_VALUE) return NO_VALUE |
| 151 | + } |
42 | 152 |
|
43 |
| - return callbackMemoized(value)(...args) |
| 153 | + return callbackMemoized(...values)(...args) |
44 | 154 | },
|
45 |
| - [callbackMemoized, facetRef], |
| 155 | + [callbackMemoized, facetsRef], |
46 | 156 | )
|
47 | 157 | }
|
0 commit comments