Skip to content
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

Call setState once when handling initial withOnyx data to reduce JS scripting time #97

Merged
merged 6 commits into from
Aug 13, 2021

Conversation

marcaaron
Copy link
Contributor

@marcaaron marcaaron commented Aug 12, 2021

Details

Implements the idea discussed in the link below cc @kidroca

Before change
2021-08-12_06-53-51

After change:
2021-08-12_06-51-51

Small difference of about 81ms here to total scripting time when the app first becomes active. But this should have positive affects in all other places where a withOnyx connection is set up.

Related Issues

Expensify/App#4592 (comment)

Automated Tests

Linked PRs

@marcaaron marcaaron self-assigned this Aug 12, 2021
@marcaaron marcaaron requested a review from a team as a code owner August 12, 2021 16:56
@MelvinBot MelvinBot requested review from nickmurray47 and removed request for a team August 12, 2021 16:56

Onyx.mergeCollection(ONYX_KEYS.COLLECTION.TEST_KEY, {test_1: {ID: 123}, test_2: {ID: 234}, test_3: {ID: 345}});
return waitForPromisesToResolve()
waitForPromisesToResolve()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these tests are fixed correctly. Did not observe any issues with mergeCollection() yet

Copy link
Contributor

@kidroca kidroca left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good work!
It seems we're pretty much moving/reusing existing code and gaining some performance
Left some minor notes

lib/withOnyx.js Outdated
Comment on lines 93 to 95
if (!_.every(requiredKeysForInit, key => !_.isUndefined(this.tempState[key]))) {
return;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO something like this is more readable:

if (_.some(requiredKeys, key => _.isUndefined(this.tempState[key])) {
  return;
}

lib/withOnyx.js Outdated
Comment on lines 97 to 99
this.setState({...this.tempState, loading: false}, () => {
this.tempState = {};
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need to reset tempState in a callback
This is equivalent and more performant

this.setState({...this.tempState, loading: false});
this.tempState = {};

Also we could delete this.tempState

lib/withOnyx.js Outdated
Comment on lines 89 to 90
setInitialState(statePropertyName, val) {
this.tempState[statePropertyName] = val;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this method should throw an Error or at least print a warning and skip execution if it's called after loading is set to false

Copy link
Contributor

@nickmurray47 nickmurray47 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@marcaaron marcaaron merged commit 2908a47 into master Aug 13, 2021
Comment on lines +89 to +93
setInitialState(statePropertyName, val) {
if (!this.state.loading) {
console.error('withOnyx.setInitialState() called after loading: false');
return;
}
Copy link
Contributor

@kidroca kidroca Aug 16, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@marcaaron
Sorry we've made a mistake here
This method is not called only for initial state but for updates (new connections) made by the logic in componentDidUpdate: https://github.com/Expensify/react-native-onyx/pull/97/files#diff-364fd7349a1af7b52091427c5a0734da8ff56057fbc7fe2be10734a06c97264cL55

We should update the logic to address calls triggered by updates

setInitialState(statePropertyName, val) {
  if (this.state.loading) {
      this.tempState[statePropertyName] = val;

    if (_.some(requiredKeysForInit, key => _.isUndefined(this.tempState[key]))) {
      return;
    }
    
    this.setState({...this.tempState, loading: false});
    delete this.tempState;
  }
  else {
     this.setState({[statePropertyName]: val});
  }
}

Also we should maybe change the method name and description to reflect that it's not called only for the initial state

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I see. The Onyx.connect() method may be called again. That solution makes sense to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for. catching this one. Created a follow up here -> #98

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants