@@ -95,7 +95,11 @@ function useOnyx<TKey extends OnyxKey, TReturnValue = OnyxValue<TKey>>(
9595 dependencies : DependencyList = [ ] ,
9696) : UseOnyxResult < TReturnValue > {
9797 const connectionRef = useRef < Connection | null > ( null ) ;
98- const previousKey = usePrevious ( key ) ;
98+ let updatedKey = key ;
99+ if ( OnyxUtils . isCollectionKey ( key ) && key . endsWith ( '_' ) ) {
100+ updatedKey = `${ key } undefined` as TKey ;
101+ }
102+ const previousKey = usePrevious ( updatedKey ) ;
99103
100104 // Used to stabilize the selector reference and avoid unnecessary calls to `getSnapshot()`.
101105 const selectorRef = useLiveRef ( options ?. selector ) ;
@@ -135,27 +139,31 @@ function useOnyx<TKey extends OnyxKey, TReturnValue = OnyxValue<TKey>>(
135139
136140 useEffect ( ( ) => {
137141 // These conditions will ensure we can only handle dynamic collection member keys from the same collection.
138- if ( options ?. allowDynamicKey || previousKey === key ) {
142+ if ( options ?. allowDynamicKey || previousKey === updatedKey ) {
139143 return ;
140144 }
141145
142146 try {
143147 const previousCollectionKey = OnyxUtils . splitCollectionMemberKey ( previousKey ) [ 0 ] ;
144- const collectionKey = OnyxUtils . splitCollectionMemberKey ( key ) [ 0 ] ;
148+ const collectionKey = OnyxUtils . splitCollectionMemberKey ( updatedKey ) [ 0 ] ;
145149
146- if ( OnyxUtils . isCollectionMemberKey ( previousCollectionKey , previousKey ) && OnyxUtils . isCollectionMemberKey ( collectionKey , key ) && previousCollectionKey === collectionKey ) {
150+ if (
151+ OnyxUtils . isCollectionMemberKey ( previousCollectionKey , previousKey ) &&
152+ OnyxUtils . isCollectionMemberKey ( collectionKey , updatedKey ) &&
153+ previousCollectionKey === collectionKey
154+ ) {
147155 return ;
148156 }
149157 } catch ( e ) {
150158 throw new Error (
151- `'${ previousKey } ' key can't be changed to '${ key } '. useOnyx() only supports dynamic keys if they are both collection member keys from the same collection e.g. from 'collection_id1' to 'collection_id2'.` ,
159+ `'${ previousKey } ' key can't be changed to '${ updatedKey } '. useOnyx() only supports dynamic keys if they are both collection member keys from the same collection e.g. from 'collection_id1' to 'collection_id2'.` ,
152160 ) ;
153161 }
154162
155163 throw new Error (
156- `'${ previousKey } ' key can't be changed to '${ key } '. useOnyx() only supports dynamic keys if they are both collection member keys from the same collection e.g. from 'collection_id1' to 'collection_id2'.` ,
164+ `'${ previousKey } ' key can't be changed to '${ updatedKey } '. useOnyx() only supports dynamic keys if they are both collection member keys from the same collection e.g. from 'collection_id1' to 'collection_id2'.` ,
157165 ) ;
158- } , [ previousKey , key , options ?. allowDynamicKey ] ) ;
166+ } , [ previousKey , updatedKey , options ?. allowDynamicKey ] ) ;
159167
160168 useEffect ( ( ) => {
161169 // This effect will only run if the `dependencies` array changes. If it changes it will force the hook
@@ -176,16 +184,16 @@ function useOnyx<TKey extends OnyxKey, TReturnValue = OnyxValue<TKey>>(
176184 return ;
177185 }
178186
179- if ( ! OnyxCache . isEvictableKey ( key ) ) {
180- throw new Error ( `canEvict can't be used on key '${ key } '. This key must explicitly be flagged as safe for removal by adding it to Onyx.init({evictableKeys: []}).` ) ;
187+ if ( ! OnyxCache . isEvictableKey ( updatedKey ) ) {
188+ throw new Error ( `canEvict can't be used on key '${ updatedKey } '. This key must explicitly be flagged as safe for removal by adding it to Onyx.init({evictableKeys: []}).` ) ;
181189 }
182190
183191 if ( options . canEvict ) {
184192 connectionManager . removeFromEvictionBlockList ( connectionRef . current ) ;
185193 } else {
186194 connectionManager . addToEvictionBlockList ( connectionRef . current ) ;
187195 }
188- } , [ key , options ?. canEvict ] ) ;
196+ } , [ updatedKey , options ?. canEvict ] ) ;
189197
190198 const getSnapshot = useCallback ( ( ) => {
191199 let isOnyxValueDefined = true ;
@@ -200,7 +208,7 @@ function useOnyx<TKey extends OnyxKey, TReturnValue = OnyxValue<TKey>>(
200208 // update `newValueRef` when `Onyx.connect()` callback is fired.
201209 if ( isFirstConnectionRef . current || shouldGetCachedValueRef . current ) {
202210 // Gets the value from cache and maps it with selector. It changes `null` to `undefined` for `useOnyx` compatibility.
203- const value = OnyxUtils . tryGetCachedValue ( key ) as OnyxValue < TKey > ;
211+ const value = OnyxUtils . tryGetCachedValue ( updatedKey ) as OnyxValue < TKey > ;
204212 const selectedValue = selectorRef . current ? selectorRef . current ( value ) : value ;
205213 newValueRef . current = ( selectedValue ?? undefined ) as TReturnValue | undefined ;
206214
@@ -213,15 +221,15 @@ function useOnyx<TKey extends OnyxKey, TReturnValue = OnyxValue<TKey>>(
213221 shouldGetCachedValueRef . current = false ;
214222 }
215223
216- const hasCacheForKey = OnyxCache . hasCacheForKey ( key ) ;
224+ const hasCacheForKey = OnyxCache . hasCacheForKey ( updatedKey ) ;
217225
218226 // Since the fetch status can be different given the use cases below, we define the variable right away.
219227 let newFetchStatus : FetchStatus | undefined ;
220228
221229 // If we have pending merge operations for the key during the first connection, we set the new value to `undefined`
222230 // and fetch status to `loading` to simulate that it is still being loaded until we have the most updated data.
223231 // If `allowStaleData` is `true` this logic will be ignored and cached value will be used, even if it's stale data.
224- if ( isFirstConnectionRef . current && OnyxUtils . hasPendingMergeForKey ( key ) && ! options ?. allowStaleData ) {
232+ if ( isFirstConnectionRef . current && OnyxUtils . hasPendingMergeForKey ( updatedKey ) && ! options ?. allowStaleData ) {
225233 newValueRef . current = undefined ;
226234 newFetchStatus = 'loading' ;
227235 }
@@ -267,20 +275,20 @@ function useOnyx<TKey extends OnyxKey, TReturnValue = OnyxValue<TKey>>(
267275 // we log an alert so it can be acknowledged by the consumer. Additionally, we won't log alerts
268276 // if there's a `Onyx.clear()` task in progress.
269277 if ( options ?. canBeMissing === false && newStatus === 'loaded' && ! isOnyxValueDefined && ! OnyxCache . hasPendingTask ( TASK . CLEAR ) ) {
270- Logger . logAlert ( `useOnyx returned no data for key with canBeMissing set to false for key ${ key } ` , { showAlert : true } ) ;
278+ Logger . logAlert ( `useOnyx returned no data for key with canBeMissing set to false for key ${ updatedKey } ` , { showAlert : true } ) ;
271279 }
272280 }
273281
274282 return resultRef . current ;
275- } , [ options ?. initWithStoredValues , options ?. allowStaleData , options ?. initialValue , options ?. canBeMissing , key , selectorRef ] ) ;
283+ } , [ options ?. initWithStoredValues , options ?. allowStaleData , options ?. initialValue , options ?. canBeMissing , updatedKey , selectorRef ] ) ;
276284
277285 const subscribe = useCallback (
278286 ( onStoreChange : ( ) => void ) => {
279287 isConnectingRef . current = true ;
280288 onStoreChangeFnRef . current = onStoreChange ;
281289
282290 connectionRef . current = connectionManager . connect < CollectionKeyBase > ( {
283- key,
291+ key : updatedKey ,
284292 callback : ( value , callbackKey , sourceValue ) => {
285293 isConnectingRef . current = false ;
286294 onStoreChangeFnRef . current = onStoreChange ;
@@ -299,7 +307,7 @@ function useOnyx<TKey extends OnyxKey, TReturnValue = OnyxValue<TKey>>(
299307 onStoreChange ( ) ;
300308 } ,
301309 initWithStoredValues : options ?. initWithStoredValues ,
302- waitForCollectionCallback : OnyxUtils . isCollectionKey ( key ) as true ,
310+ waitForCollectionCallback : OnyxUtils . isCollectionKey ( updatedKey ) as true ,
303311 reuseConnection : options ?. reuseConnection ,
304312 } ) ;
305313
@@ -316,7 +324,7 @@ function useOnyx<TKey extends OnyxKey, TReturnValue = OnyxValue<TKey>>(
316324 onStoreChangeFnRef . current = null ;
317325 } ;
318326 } ,
319- [ key , options ?. initWithStoredValues , options ?. reuseConnection , checkEvictableKey ] ,
327+ [ updatedKey , options ?. initWithStoredValues , options ?. reuseConnection , checkEvictableKey ] ,
320328 ) ;
321329
322330 const getSnapshotDecorated = useMemo ( ( ) => {
0 commit comments