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

Efficient React ListView for Realm collections #199

Merged
merged 16 commits into from
Feb 17, 2016
Merged

Efficient React ListView for Realm collections #199

merged 16 commits into from
Feb 17, 2016

Conversation

appden
Copy link
Contributor

@appden appden commented Jan 12, 2016

This component is fully backwards compatible with the original React ListView, but is compatible with Realm Results and List objects to use their snapshot functionality along with more efficiently checking if each row should update.

This resolves #142 and #36

@appden
Copy link
Contributor Author

appden commented Jan 12, 2016

retest this please

const TodoListItem = require('./todo-list-item');
const realm = require('./realm');
const styles = require('./styles');

const { ListView, Text, View } = React;
const { Text, View } = React;
const { ListView } = RealmReact;
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we consider naming it RealmListView to differentiate? This is fine if it is the convention but may be confusing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No because it's supposed to be a drop-in replacement and it's namespace under the RealmReact module. So it's really called RealmReact.ListView.

@alazier
Copy link
Contributor

alazier commented Jan 12, 2016

Have we done any testing to see how this effects performance? Would be good to know if this resolves any of the issues reported.

We should also probably write tests for this.

@appden
Copy link
Contributor Author

appden commented Jan 13, 2016

I have a separate test app where I fine tuned this to work with a reasonably large dataset (100,000 items). It removed all the JS bottlenecks, but there's definitely a performance issue with using large sorted results (inside core) that I will dive more into when I address #193.

I don't think the overhead of creating UI tests for this will be worth the effort at this point.

});

this.state = {};
this.state = {
dataSource: this._cloneDataSource(dataSource, props),
Copy link
Contributor

Choose a reason for hiding this comment

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

I haven't been following the evolution completely so maybe I am missing something, but it seems odd to me that a data source would be state rather than a property or just a variable.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is a bit weird at first, but since a dataSource is completely immutable it makes sense because the canonical way to update it is to clone it and call setState. Otherwise you'd need to call forceUpdate, which is kind of an anti-pattern in React.

@alazier
Copy link
Contributor

alazier commented Jan 14, 2016

Playing around with this a bit it looks like we have some perf issues. I added this code to the TodoApp constructor to populate the initial list with 1000 items:

                let list = realm.create('TodoList', {name: 'Todo List', items: []});
                for (var i = 0; i < 1000; i++) {
                    list.items.push({text: '' + i});
                };

After doing this scrolling performance is pretty bad, and there is a noticeable lag when mutating the list by removing items. The lag increases to further you scroll down - once you get down to around 300 items the ui takes about a second to update. It would be nice to know where this lag is coming from and to eliminate it if possible.

@appden
Copy link
Contributor Author

appden commented Jan 15, 2016

I had to dive in pretty deep with the JavaScriptCore profiler to understand what's going here. This delay is overwhelmingly caused by React validating props, which is only enabled on debug builds. When built in Release mode, this problem should go away. However, we don't have the necessary build phase in the example app to bundle the release version of the JS (I will update this branch with that phase). You can get the release version of the JS by appending &dev=false to the bundle URL in AppDelegate.m, and you will see that there is no more delay when deleting todo items. 😄

@appden
Copy link
Contributor Author

appden commented Jan 15, 2016

I opened PR #202 with updates to the way the example app chooses its JS.

@alazier
Copy link
Contributor

alazier commented Jan 19, 2016

I think this is fine other than the fact that we don't have tests verifying that this works. It is likely that at some point react-native will change and this will break. I think at a minimum we should add ui tests to the example app to make sure list items actually show up using our ListView. Since this is something we have been meaning to do anyway it may make sense to make it happen with this pr.

@appden
Copy link
Contributor Author

appden commented Jan 21, 2016

Ok, I'll try to tackle a basic version of that for this PR.

This would unfortunately result in adverse performance side effects because calling size() can be expensive.
This component is fully backwards compatible with the original React ListView, but is compatible with Realm Results and List objects to use their snapshot functionality along with more efficiently checking if each row should update.
It's also been updated to follow best practices with how to properly use the ListView data source.
This caused an error with NPM v3 and was not necessary for us to have.
* master: (207 commits)
  Convert to using new React Native MainActivity template
  Create RealmReactPackage for our Android plugin
  Fix doc for Android
  NPM ignore react-native/android folder
  Skip building Android module under Xcode
  Skip building Android module for iOS tests
  gitignore Android downloads folder
  Update README with instructions to run on Android
  Use un-patched RN for Android by installing hook into JSC
  cleanup build system
  Use Realm in node_modules for ReactTests on Android
  Change Demo => ReactTests
  adding a 'publishAndroid' task to generate the AAR with prebuilt .so files
  Adjust POM_NAME
  Use consistent package naming
  Remove old Demo files
  Add copyright to JNI file
  Cleanup platform.hpp
  Make our Android module buildable as a dependency
  Add `npm test` command
  ...
These changes include timeouts when waiting on notifications.
Re-using the existing React testing class to hook into the example app. Right now, the test is extremely basic but is able to be expanded later.

Resolves #36
@appden
Copy link
Contributor Author

appden commented Feb 16, 2016

@alazier this is ready for review. It includes the ListView implementation that you reviewed before, and lots of updates to test that the ReactExample app properly loads as well as new unit tests for ListViewDataSource inside the ReactTests app.

alazier added a commit that referenced this pull request Feb 17, 2016
Efficient React ListView for Realm collections
@alazier alazier merged commit d9abcf0 into master Feb 17, 2016
@appden appden deleted the sk-listview branch February 19, 2016 00:31
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 17, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Build a RealmListViewDataSource
3 participants