Allow infinite dependent keys when using withOnyx#355
Conversation
| }, | ||
| })(ViewWithCollections); | ||
| render(<TestComponentWithOnyx markReadyForHydration={markReadyForHydration} onRender={onRender} />); | ||
| return waitForPromisesToResolve(); |
There was a problem hiding this comment.
I also found that the test wouldn't pass without this being added, which I think is normal. I'm not sure why it was removed as it existed when the test was originally written.
| const TestComponentWithOnyx = withOnyx({ | ||
| testObject: { | ||
| key: `${ONYX_KEYS.COLLECTION.TEST_KEY}${collectionItemID}`, | ||
| }, | ||
| testThing: { | ||
| key: ({testObject}) => `${ONYX_KEYS.COLLECTION.RELATED_KEY}${(testObject && testObject.id) || 0}`, | ||
| }, | ||
| })(ViewWithCollections); |
There was a problem hiding this comment.
Nice job updating these tests. Can you maybe add another key which is dependent on testThing? This will verify that n layer of nesting can be avoided by this flattened out structure!
There was a problem hiding this comment.
Yeah, that's a great idea. I will add that!
lib/withOnyx.js
Outdated
| const previousKey = Str.result(mapping.key, {...prevProps, ...prevState}); | ||
| const newKey = Str.result(mapping.key, {...this.props, ...this.state}); |
There was a problem hiding this comment.
Adding this.state directly might lead the exposure of some state properties like this.state.loading that shouldn't be visible to the end user. Do you think its a deal breaker?
There was a problem hiding this comment.
It's probably not a deal-breaker (until someone starts abusing it), but it would be easy to also omit all keys from the state which aren't part of the mappings. I can add that.
lib/withOnyx.js
Outdated
| const mappingPropNames = _.keys(mapOnyxToState); | ||
| const stateOnlyWithOnyxData = _.pick(this.state, mappingPropNames); |
There was a problem hiding this comment.
Would be better to move this to another function since its being used at top as well.
lib/withOnyx.js
Outdated
| const key = Str.result(mapping.key, {...this.props, ...this.state}); | ||
| const mappingPropNames = _.keys(mapOnyxToState); | ||
| const stateOnlyWithOnyxData = _.pick(this.state, mappingPropNames); | ||
| const key = Str.result(mapping.key, {...this.props, ...stateOnlyWithOnyxData}); |
There was a problem hiding this comment.
Probably, this can also go into that same function.
There was a problem hiding this comment.
Sure, good idea. I've updated it to DRY up this logic and move it into a simple function defined at the top of the module.
| staticObject: { | ||
| key: `${ONYX_KEYS.COLLECTION.STATIC}1`, | ||
| }, | ||
| testThing: { | ||
| key: ({testObject}) => `${ONYX_KEYS.COLLECTION.RELATED_KEY}${(testObject && testObject.id) || 0}`, | ||
| dependentObject: { | ||
| key: ({staticObject}) => `${ONYX_KEYS.COLLECTION.DEPENDS_ON_STATIC}${(staticObject && staticObject.id) || 0}`, | ||
| }, | ||
| multiDependentObject: { | ||
| key: ({dependentObject}) => `${ONYX_KEYS.COLLECTION.DEPENDS_ON_DEPENDS_ON_STATIC}${(dependentObject && dependentObject.id) || 0}`, | ||
| }, | ||
| extremeMultiDependentObject: { | ||
| key: ({multiDependentObject}) => `${ONYX_KEYS.COLLECTION.DEPENDS_ON_DEPENDS_ON_DEPENDS_ON_STATIC}${(multiDependentObject && multiDependentObject.id) || 0}`, |
|
Unfortunately, when tested in App, this caused major performance problems that locks up the browser. So, while it is a great change, I guess there are some other considerations that need to be made for this to be viable. CC @chrispader @kidroca @hannojg I'd love to brainstorm with you guys on this one. |
@tgolen sorry that i didn't respond yet. i'm gonna try to look into this issue this week, if nothing has changed 👍🏼 |
|
Thanks, Chris! I redid the original PR in #385 and I am unable to reproduce any of the original performance problems, so I don't know that we need to do anything more yet at this point. |
Details
I found that the dependent keys weren't being loaded because we were only passing
propsto the key functions. This won't contain the already loaded Onyx data because that data is only stored in the HOC'sstate.The solution is to pass both the
propsand thestateto the key functions.There were a couple more fixes I had to do to ensure multiple levels of depencies are resolved as expected.
Related Issues
Fixes Expensify/App#27906
Automated Tests
All covered by unit tests
Linked PRs
TBD