-
Notifications
You must be signed in to change notification settings - Fork 74
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix: issues in Onyx bump due to removal of null values in cache #558
Fix: issues in Onyx bump due to removal of null values in cache #558
Conversation
@chrispader Can you please provide more details for the PR and also ideally cover some of these changes in new tests wherever it would make sense? It been lots of changes without specific tests @blazejkustra @fabioh8010 can you please review this PR too? |
7601a53
to
cdf0c78
Compare
@mountiny updated the PR description. This PR should fix all remaining issues in the Onyx bump PR (so far). @blazejkustra @fabioh8010 the TS changes are mostly related to similar changes i made in a previous PR, related to Onyx input types ( |
ready for review! 🚀 |
@mountiny working on adding new tests for these changes today! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@chrispader Nice work, left few comments!
Could you apply these changes too? We don't need them anymore since we get rid of null
.
diff --git a/lib/useOnyx.ts b/lib/useOnyx.ts
index 958170b..230cbaf 100644
--- a/lib/useOnyx.ts
+++ b/lib/useOnyx.ts
@@ -2,21 +2,11 @@ import {deepEqual} from 'fast-equals';
import {useCallback, useEffect, useRef, useSyncExternalStore} from 'react';
import type {IsEqual} from 'type-fest';
import OnyxUtils from './OnyxUtils';
-import type {CollectionKeyBase, KeyValueMapping, NonNull, OnyxCollection, OnyxEntry, OnyxKey, Selector} from './types';
+import type {CollectionKeyBase, OnyxCollection, OnyxKey, OnyxValue, Selector} from './types';
import useLiveRef from './useLiveRef';
import usePrevious from './usePrevious';
import Onyx from './Onyx';
-/**
- * Represents a Onyx value that can be either a single entry or a collection of entries, depending on the `TKey` provided.
- * It's a variation of `OnyxValue` type that is read-only and excludes the `null` type.
- */
-type UseOnyxValue<TKey extends OnyxKey> = string extends TKey
- ? unknown
- : TKey extends CollectionKeyBase
- ? NonNull<OnyxCollection<KeyValueMapping[TKey]>>
- : NonNull<OnyxEntry<KeyValueMapping[TKey]>>;
-
type BaseUseOnyxOptions = {
/**
* Determines if this key in this subscription is safe to be evicted.
@@ -55,7 +45,7 @@ type UseOnyxOptions<TKey extends OnyxKey, TReturnValue> = BaseUseOnyxOptions & U
type FetchStatus = 'loading' | 'loaded';
-type CachedValue<TKey extends OnyxKey, TValue> = IsEqual<TValue, UseOnyxValue<TKey>> extends true ? TValue : TKey extends CollectionKeyBase ? NonNullable<OnyxCollection<TValue>> : TValue;
+type CachedValue<TKey extends OnyxKey, TValue> = IsEqual<TValue, OnyxValue<TKey>> extends true ? TValue : TKey extends CollectionKeyBase ? NonNullable<OnyxCollection<TValue>> : TValue;
type ResultMetadata = {
status: FetchStatus;
@@ -67,15 +57,15 @@ function getCachedValue<TKey extends OnyxKey, TValue>(key: TKey, selector?: Sele
return OnyxUtils.tryGetCachedValue(key, {selector}) as CachedValue<TKey, TValue> | undefined;
}
-function useOnyx<TKey extends OnyxKey, TReturnValue = UseOnyxValue<TKey>>(
+function useOnyx<TKey extends OnyxKey, TReturnValue = OnyxValue<TKey>>(
key: TKey,
options?: BaseUseOnyxOptions & UseOnyxInitialValueOption<TReturnValue> & Required<UseOnyxSelectorOption<TKey, TReturnValue>>,
): UseOnyxResult<TKey, TReturnValue>;
-function useOnyx<TKey extends OnyxKey, TReturnValue = UseOnyxValue<TKey>>(
+function useOnyx<TKey extends OnyxKey, TReturnValue = OnyxValue<TKey>>(
key: TKey,
options?: BaseUseOnyxOptions & UseOnyxInitialValueOption<NoInfer<TReturnValue>>,
): UseOnyxResult<TKey, TReturnValue>;
-function useOnyx<TKey extends OnyxKey, TReturnValue = UseOnyxValue<TKey>>(key: TKey, options?: UseOnyxOptions<TKey, TReturnValue>): UseOnyxResult<TKey, TReturnValue> {
+function useOnyx<TKey extends OnyxKey, TReturnValue = OnyxValue<TKey>>(key: TKey, options?: UseOnyxOptions<TKey, TReturnValue>): UseOnyxResult<TKey, TReturnValue> {
const connectionIDRef = useRef<number | null>(null);
const previousKey = usePrevious(key);
@fabioh8010 thanks for mentioning these issues. I added your changes and updated the comments :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Type changes look good to me! I really like the idea to replace null
with undefined
👍
Do I understand correctly that null
will still be used but only when we want to remove a property from an onyx value/remove whole onyx value?
@blazejkustra yes exactly. passing Onyx will never persist and return |
@fabioh8010 @blazejkustra just added one more type that we're gonna use in E/App, so you can probably ignore reviewing the last two commit, because it's just a TS type export |
@chrispader I was checking the last changes and I found an TS issue with Onyx.mergeCollection(ONYXKEYS.COLLECTION.DOWNLOAD, {
[`${ONYXKEYS.COLLECTION.DOWNLOAD}${'attachment1'}` as const]: {isDownloading: true},
[`${ONYXKEYS.COLLECTION.DOWNLOAD}${'attachment3'}` as const]: {isDownloading: true},
[`${ONYXKEYS.COLLECTION.REPORT}${'report1'}` as const]: {isDownloading: true}, // TS is allowing to pass a report item with a download object, previously it would raise an error
}); EDIT: It seems that the issue is fixed if I revert these changes, why do we need them @chrispader ? |
This reverts commit 4e893aa.
@fabioh8010 yes you're right. I thought we could pass the type of the collection to Reverted the changes and added back the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the changes, all bugs found in the App PR has been addressed it seems so lets get this out so we can make a new build for Applause
🚀Published to npm in v2.0.47 |
@mountiny
Details
This PR fixes minor issues in Onyx arising from this Onyx bump PR.
undefined
values in cache and storage, whenundefined
is passed toOnyx.set
/Onyx.merge
/...Onyx.multiSet
OnyxUtils.getCachedCollection
should only returnundefined
keys that are actually set in cache. (We need strict objects with not set keys rather then keys that areundefined
when not existing)deepEqual
comparisons inkeyChanged
andkeysChanged
(and prefer easier-to-read early-returns) (improve naming of some variables and make them more consistent)mergeObject
we're trying to access a key ontarget
, even thoughtarget
might not even be an objectwithOnyx
where we check if all state entries intempState
are non-undefined
, rather than checking if the keys exist. This caused components to never exit the loading state inwithOnyx
and therefore never renderThe PR also adds some TS type changes and improvements related to Onyx input values, that also stem from this Onyx bump PR.
Related Issues
margelo/expensify-app-fork#20
Automated Tests
Manual Tests
Author Checklist
### Related Issues
section aboveTests
sectiontoggleReport
and notonIconClick
)myBool && <MyComponent />
.STYLE.md
) were followedAvatar
, I verified the components usingAvatar
are working as expected)/** comment above it */
this
properly so there are no scoping issues (i.e. foronClick={this.submit}
the methodthis.submit
should be bound tothis
in the constructor)this
are necessary to be bound (i.e. avoidthis.submit = this.submit.bind(this);
ifthis.submit
is never passed to a component event handler likeonClick
)Avatar
is modified, I verified thatAvatar
is working as expected in all cases)main
branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTest
steps.Screenshots/Videos
Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari
MacOS: Desktop