Conversation
|
Is there an App issue to link to? Even if the change is good is there some issue explaining why this change is needed now? |
|
Context here @chiragsalian, but I think it's good to run this by Callstack (or SWM) first. |
|
Asked here. |
|
Cool, thank you |
lib/withOnyx.d.ts
Outdated
| | BaseMappingStringKeyAndSelector<TComponentProps, TOnyxProps, Partial<KeyValueMapping[TOnyxKey]>, TOnyxKey> | ||
| | BaseMappingFunctionKeyAndSelector<TComponentProps, TOnyxProps, Partial<KeyValueMapping[TOnyxKey]>, TOnyxKey> |
There was a problem hiding this comment.
| | BaseMappingStringKeyAndSelector<TComponentProps, TOnyxProps, Partial<KeyValueMapping[TOnyxKey]>, TOnyxKey> | |
| | BaseMappingFunctionKeyAndSelector<TComponentProps, TOnyxProps, Partial<KeyValueMapping[TOnyxKey]>, TOnyxKey> | |
| | BaseMappingStringKeyAndSelector<TComponentProps, TOnyxProps, ExtractOnyxCollectionValue<TOnyxProps[TOnyxProp]>, TOnyxKey> | |
| | BaseMappingFunctionKeyAndSelector<TComponentProps, TOnyxProps, ExtractOnyxCollectionValue<TOnyxProps[TOnyxProp]>, TOnyxKey> |
@tienifr We have two issues here:
-
By changing
TOnyxProps[TOnyxProp]toPartial<KeyValueMapping[TOnyxKey]>we lose all type equality check between the components'OnyxPropsandwithOnyxmapping, which means that we could type anything in the Onyx prop and the selector wouldn't be able to check if its return type matches with the corresponding Onyx prop. -
Also, by doing
Partial<KeyValueMapping[TOnyxKey]>you are limiting the selector's return to be an object with optional properties of that Onyx value, which is not always the case.When we have a combination of a collection key and a
selector, thewithOnyxwill runselectorfunction for each entry of that collection and build a collection object with the results of allselectorexecutions, for example:type ContactMethodDetailsPageOnyxProps = { policiesIDs: OnyxCollection<string>; }; ... export default withOnyx<ContactMethodDetailsPageProps, ContactMethodDetailsPageOnyxProps>({ policiesIDs: { key: ONYXKEYS.COLLECTION.POLICY, selector: (data) => data?.id ?? '', // this is valid and will make policies return a collection of ids }, })(ContactMethodDetailsPage);
To improve these typings, my suggestion is:
- Add this type in
lib/types.d.tswhich will make possible extracting the value of a Onyx collection:... type OnyxCollection<TOnyxValue> = OnyxEntry<Record<string, TOnyxValue | null>>; /** * Utility type to extract `TOnyxValue` from `OnyxCollection<TOnyxValue>`. */ type ExtractOnyxCollectionValue<TOnyxCollection> = TOnyxCollection extends NonNullable<OnyxCollection<infer U>> ? U : never; ...
- Use it in
CollectionMapping:/** * Represents the mapping options between an Onyx collection key without suffix and the component's prop with all its possibilities. */ type CollectionMapping<TComponentProps, TOnyxProps, TOnyxProp extends keyof TOnyxProps, TOnyxKey extends CollectionKeyBase> = BaseMapping<TComponentProps, TOnyxProps> & CollectionBaseMapping<TOnyxKey> & ( | BaseMappingKey<TComponentProps, TOnyxProps, TOnyxProp, TOnyxKey, OnyxCollection<KeyValueMapping[TOnyxKey]>> | BaseMappingStringKeyAndSelector<TComponentProps, TOnyxProps, ExtractOnyxCollectionValue<TOnyxProps[TOnyxProp]>, TOnyxKey> | BaseMappingFunctionKeyAndSelector<TComponentProps, TOnyxProps, ExtractOnyxCollectionValue<TOnyxProps[TOnyxProp]>, TOnyxKey> );
This way we can ensure the type equality checks will still work and get rid of these issues when using the selector. For your case in this discussion, final solution would be like this:
type ContactMethodDetailsPageOnyxProps = {
...
policies: OnyxCollection<Pick<Policy, 'id' | 'ownerAccountID'>>;
};
...
export default withOnyx<ContactMethodDetailsPageProps, ContactMethodDetailsPageOnyxProps>({
...
policies: {
key: ONYXKEYS.COLLECTION.POLICY,
selector: (data) => ({id: data?.id ?? '', ownerAccountID: data?.ownerAccountID}),
},
})(ContactMethodDetailsPage);|
@fabioh8010 I'd love your idea above^. It works for me. Using |
lib/withOnyx.d.ts
Outdated
| | BaseMappingStringKeyAndSelector<TComponentProps, TOnyxProps, ExtractOnyxCollectionValue<TOnyxProps[TOnyxProp]>, TOnyxKey> | ||
| | BaseMappingFunctionKeyAndSelector<TComponentProps, TOnyxProps, ExtractOnyxCollectionValue<TOnyxProps[TOnyxProp]>, TOnyxKey> |
There was a problem hiding this comment.
| | BaseMappingStringKeyAndSelector<TComponentProps, TOnyxProps, ExtractOnyxCollectionValue<TOnyxProps[TOnyxProp]>, TOnyxKey> | |
| | BaseMappingFunctionKeyAndSelector<TComponentProps, TOnyxProps, ExtractOnyxCollectionValue<TOnyxProps[TOnyxProp]>, TOnyxKey> | |
| | BaseMappingStringKeyAndSelector<TComponentProps, TOnyxProps, TOnyxProps[TOnyxProp], TOnyxKey> | |
| | BaseMappingFunctionKeyAndSelector<TComponentProps, TOnyxProps, TOnyxProps[TOnyxProp], TOnyxKey> |
You changed the wrong Mapping 😅
lib/withOnyx.d.ts
Outdated
| | BaseMappingStringKeyAndSelector<TComponentProps, TOnyxProps, TOnyxProps[TOnyxProp], TOnyxKey> | ||
| | BaseMappingFunctionKeyAndSelector<TComponentProps, TOnyxProps, TOnyxProps[TOnyxProp], TOnyxKey> |
There was a problem hiding this comment.
| | BaseMappingStringKeyAndSelector<TComponentProps, TOnyxProps, TOnyxProps[TOnyxProp], TOnyxKey> | |
| | BaseMappingFunctionKeyAndSelector<TComponentProps, TOnyxProps, TOnyxProps[TOnyxProp], TOnyxKey> | |
| | BaseMappingStringKeyAndSelector<TComponentProps, TOnyxProps, ExtractOnyxCollectionValue<TOnyxProps[TOnyxProp]>, TOnyxKey> | |
| | BaseMappingFunctionKeyAndSelector<TComponentProps, TOnyxProps, ExtractOnyxCollectionValue<TOnyxProps[TOnyxProp]>, TOnyxKey> |
|
Thanks for pointing that out. I updated the PR @fabioh8010 |
|
Hmm actually it doesn't work at all, not due to TS checks, but I see that we use |
|
@youssef-lr Do you mind sharing the code that isn't working? I tested here and the types are correct.
|
|
Hm I think the changes in react-native-onyx are not being reflected for me locally, here's what I did:
Am I missing something? |
|
@youssef-lr After doing |
|
Yeah I was just doing that now |
|
They are updated..maybe it's just an issue with my editor. Thanks for checking! |
|
Any idea why the selector takes a single policy instead of all the policies from the collection? Probably out of scope here, but I was under the assumption the param of the selector should be all of the policies Edit: I think it has always been like this..I will bring up a discussion in Slack as I'm curious if we'd have a need for a selector returning all policies and then we can use a |
Co-authored-by: Błażej Kustra <46095609+blazejkustra@users.noreply.github.com>
|
CLA Assistant Lite bot All contributors have signed the CLA ✍️ ✅ |
|
I have read the CLA Document and I hereby sign the CLA |
|
@youssef-lr When we have this combination of a collection key and |
|
I wonder if we could update that such as if the selector returns |
|
So here's a use case I'm thinking of, suppose we have a component that only needs a subset of a collection to subscribe to, we don't want re-renders if other items from that collection changes, I think only passing the items to the component would be beneficial here. Buuut, I suppose filtering out |



Details
Related Issues
GH_LINK
Automated Tests
Manual Tests
Author Checklist
### Related Issuessection aboveTestssectiontoggleReportand notonIconClick)myBool && <MyComponent />.STYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)/** comment above it */thisproperly so there are no scoping issues (i.e. foronClick={this.submit}the methodthis.submitshould be bound tothisin the constructor)thisare necessary to be bound (i.e. avoidthis.submit = this.submit.bind(this);ifthis.submitis never passed to a component event handler likeonClick)Avataris modified, I verified thatAvataris working as expected in all cases)mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari
MacOS: Desktop