diff --git a/examples/ReactExample/.eslintrc b/examples/ReactExample/.eslintrc
new file mode 100644
index 00000000..98b5f8ba
--- /dev/null
+++ b/examples/ReactExample/.eslintrc
@@ -0,0 +1,20 @@
+{
+ "env": {
+ "commonjs": true,
+ "es6": true
+ },
+ "ecmaFeatures": {
+ "jsx": true
+ },
+ "plugins": [
+ "react"
+ ],
+ "rules": {
+ "react/jsx-no-duplicate-props": 2,
+ "react/jsx-no-undef": 2,
+ "react/jsx-uses-react": 2,
+ "react/no-direct-mutation-state": 1,
+ "react/prefer-es6-class": 1,
+ "react/react-in-jsx-scope": 2
+ }
+}
diff --git a/examples/ReactExample/components/realm.js b/examples/ReactExample/components/realm.js
new file mode 100644
index 00000000..7a62e345
--- /dev/null
+++ b/examples/ReactExample/components/realm.js
@@ -0,0 +1,21 @@
+'use strict';
+
+const Realm = require('realm');
+
+module.exports = new Realm({
+ schema: [
+ {
+ name: 'Todo',
+ properties: [
+ {name: 'text', type: Realm.Types.STRING},
+ ]
+ },
+ {
+ name: 'TodoList',
+ properties: [
+ {name: 'name', type: Realm.Types.STRING},
+ {name: 'items', type: Realm.Types.LIST, objectType: 'Todo'},
+ ]
+ },
+ ],
+});
diff --git a/examples/ReactExample/components/styles.js b/examples/ReactExample/components/styles.js
new file mode 100644
index 00000000..d02ea704
--- /dev/null
+++ b/examples/ReactExample/components/styles.js
@@ -0,0 +1,34 @@
+'use strict';
+
+const React = require('react-native');
+
+module.exports = React.StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'stretch',
+ backgroundColor: '#ffffff',
+ },
+ listItem: {
+ padding: 12,
+ borderColor: "#c8c7cc",
+ borderBottomWidth: 0.5,
+ alignItems: 'center',
+ alignSelf: 'stretch',
+ flexDirection: 'row',
+ flex: 1,
+ height: 44,
+ },
+ listItemText: {
+ fontFamily: 'System',
+ fontSize: 15,
+ flexDirection: 'column',
+ flex: 1,
+ lineHeight: 16,
+ },
+ instructions: {
+ textAlign: 'center',
+ color: '#333333',
+ marginBottom: 5,
+ }
+});
diff --git a/examples/ReactExample/components/todo-app.js b/examples/ReactExample/components/todo-app.js
new file mode 100644
index 00000000..afebfc09
--- /dev/null
+++ b/examples/ReactExample/components/todo-app.js
@@ -0,0 +1,51 @@
+'use strict';
+
+const React = require('react-native');
+const TodoList = require('./todo-list');
+const realm = require('./realm');
+
+const { NavigatorIOS } = React;
+
+class TodoApp extends React.Component {
+ componentWillMount() {
+ let todoLists = realm.objects('TodoList');
+
+ if (todoLists.length < 1) {
+ realm.write(() => {
+ realm.create('TodoList', {name: 'Todo List', items: []});
+ });
+ }
+
+ this.todoLists = todoLists;
+ }
+
+ render() {
+ let list = this.todoLists[0];
+
+ let route = {
+ title: list.name,
+ component: TodoList,
+ passProps: {
+ ref: 'todoList',
+ list: list,
+ },
+ rightButtonTitle: 'Add',
+ onRightButtonPress: () => this._addNewItem(list)
+ };
+
+ return (
+
+ );
+ }
+
+ _addNewItem(list) {
+ realm.write(() => {
+ list.items.push({text: ''});
+ });
+
+ let todoList = this.refs.nav.refs.todoList;
+ todoList.setState({editingRow: list.items.length - 1});
+ }
+}
+
+module.exports = TodoApp;
diff --git a/examples/ReactExample/components/todo-item.js b/examples/ReactExample/components/todo-item.js
new file mode 100644
index 00000000..1ca68343
--- /dev/null
+++ b/examples/ReactExample/components/todo-item.js
@@ -0,0 +1,77 @@
+'use strict';
+
+const React = require('react-native');
+const realm = require('./realm');
+const styles = require('./styles');
+
+const { Text, TextInput, View } = React;
+
+class TodoItem extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this._onChangeText = this._onChangeText.bind(this);
+ }
+
+ componentDidMount() {
+ // The autoFocus prop on TextInput was not working for us :(
+ this._focusInputIfNecessary();
+ }
+
+ componentDidUpdate() {
+ this._focusInputIfNecessary();
+ }
+
+ render() {
+ let contents;
+
+ if (this.props.editing) {
+ contents = (
+
+ );
+ } else {
+ contents = (
+
+ {this.props.item.text}
+
+ );
+ }
+
+ return (
+
+ {contents}
+
+ );
+ }
+
+ _onChangeText(text) {
+ realm.write(() => {
+ this.props.item.text = text;
+ });
+
+ this.forceUpdate();
+ }
+
+ _focusInputIfNecessary() {
+ if (!this.props.editing) {
+ return;
+ }
+
+ let input = this.refs.input;
+ if (!input.isFocused()) {
+ input.focus();
+ }
+ }
+}
+
+module.exports = TodoItem;
diff --git a/examples/ReactExample/components/todo-list.js b/examples/ReactExample/components/todo-list.js
new file mode 100644
index 00000000..c292f2d9
--- /dev/null
+++ b/examples/ReactExample/components/todo-list.js
@@ -0,0 +1,70 @@
+'use strict';
+
+const React = require('react-native');
+const TodoItem = require('./todo-item');
+const realm = require('./realm');
+const styles = require('./styles');
+
+const { ListView, Text, View } = React;
+
+class TodoList extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.dataSource = new ListView.DataSource({
+ rowHasChanged: (row1, row2) => row1 !== row2
+ });
+
+ this.state = {};
+ this._renderRow = this._renderRow.bind(this);
+ }
+
+ render() {
+ let dataSource = this.dataSource.cloneWithRows(this.props.list.items);
+
+ return (
+
+
+
+ Press Cmd+R to reload,{'\n'}
+ Cmd+D for dev menu
+
+
+ );
+ }
+
+ _renderRow(item, sectionIndex, rowIndex) {
+ return (
+ this._onPressRow(rowIndex)}
+ onEndEditing={() => this._onEndEditingRow(rowIndex)} />
+ );
+ }
+
+ _onPressRow(rowIndex) {
+ let editingRow = this.state.editingRow;
+
+ if (editingRow != null && editingRow != rowIndex) {
+ this._onEndEditingRow(editingRow);
+ }
+
+ this.setState({editingRow: rowIndex});
+ }
+
+ _onEndEditingRow(rowIndex) {
+ let items = this.props.list.items;
+
+ // Delete the todo item if it doesn't have any text.
+ if (!items[rowIndex].text) {
+ realm.write(() => items.splice(rowIndex, 1));
+ }
+
+ if (this.state.editingRow == rowIndex) {
+ this.setState({editingRow: null});
+ }
+ }
+}
+
+module.exports = TodoList;
diff --git a/examples/ReactExample/index.ios.js b/examples/ReactExample/index.ios.js
index 4fd74391..e051fe32 100644
--- a/examples/ReactExample/index.ios.js
+++ b/examples/ReactExample/index.ios.js
@@ -1,198 +1,6 @@
-/**
- * Sample React Native App
- * https://github.com/facebook/react-native
- */
'use strict';
-var Realm = require('realm');
-var React = require('react-native');
+const React = require('react-native');
+const TodoApp = require('./components/todo-app');
-var {
- AppRegistry,
- StyleSheet,
- NavigatorIOS,
- AlertIOS,
- ListView,
- TouchableHighlight,
- Text,
- TextInput,
- View,
-} = React;
-
-var TodoItemSchema = {
- name: 'Todo',
- properties: [
- {name: 'text', type: Realm.Types.STRING},
- ]
-};
-var TodoListSchmea = {
- name: 'TodoList',
- properties: [
- {name: 'name', type: Realm.Types.STRING},
- {name: 'items', type: Realm.Types.LIST, objectType: 'Todo'}
- ]
-};
-
-console.log(Realm.defaultPath);
-var realm = new Realm({schema: [TodoItemSchema, TodoListSchmea]});
-
-class Edit extends React.Component {
- componentWillMount() {
- this.setState({text: this.props.text});
- }
-
- save() {
- realm.write(function () {
- if (this.props.todoId == this.props.list.items.length) {
- this.props.list.items.push({text: this.state.text});
- }
- else {
- var todoItem = this.props.list.items[this.props.todoId];
- todoItem.text = this.state.text;
- }
- }.bind(this));
- // should not be needed once we have notifications
- this.props.parent.updateDataSource();
- this.props.navigator.pop();
- }
-
- render() {
- return (
-
- this.setState({text})} value={this.state.text}/>
-
- Save
-
-
- )
- }
-};
-
-class TodoList extends React.Component {
- componentWillMount() {
- this.lists = realm.objects('TodoList');
- if (this.lists.length < 1) {
- realm.write(function() {
- realm.create('TodoList', ['List', []]);
- });
- }
- this.list = this.lists[0];
- this.menu = this.menu.bind(this);
- this.delete = this.delete.bind(this);
- var dataSource = new ListView.DataSource({
- rowHasChanged: (row1, row2) => row1 !== row2
- });
-
- this.updateDataSource(dataSource);
- }
-
- updateDataSource(oldDataSource) {
- if (!oldDataSource) {
- oldDataSource = this.state.dataSource;
- }
- this.setState({dataSource: oldDataSource.cloneWithRows(this.list.items)});
- }
-
- menu(todo, todoID) {
- AlertIOS.alert(
- todo.text,
- todoID,
- [
- {text: 'Complete', onPress: () => this.delete(todoID)},
- {text: 'Edit', onPress: () => this.edit(todoID, todo.text)},
- {text: 'Cancel'}
- ]
- )
- }
-
- delete(todoID) {
- var item = this.list.items[todoID];
- realm.write(function() {
- realm.delete(item);
- })
- this.updateDataSource();
- }
-
- edit(todoId, text) {
- this.props.navigator.push({
- title: text,
- component: Edit,
- passProps: {list: this.list, todoId: todoId, text: text, parent: this}
- });
- }
-
- render() {
- return (
-
-
- this.menu(rowData, rowID)}>
- {rowData.text}
-
- }/>
- this.edit(this.list.items.length, "")}>
- +
-
-
- Press Cmd+R to reload,{'\n'}
- Cmd+Control+Z for dev menu
-
-
- );
- }
-};
-
-class Navigator extends React.Component {
- render() {
- return (
-
- );
- }
-};
-AppRegistry.registerComponent('ReactExample', () => Navigator);
-
-var styles = StyleSheet.create({
- container: {
- flex: 1,
- justifyContent: 'center',
- alignItems: 'stretch',
- backgroundColor: '#ffffff',
- },
- listItem: {
- marginTop: 3,
- padding: 6,
- backgroundColor:'#ACACAC',
- alignSelf: 'stretch',
- flexDirection: 'row',
- flex:1,
- },
- textInput: {
- alignSelf: 'stretch',
- borderWidth: 0.5,
- borderColor: '#0f0f0f',
- height: 200,
- fontSize: 13,
- margin: 6,
- marginTop: 70,
- padding: 4,
- },
- button: {
- height: 36,
- backgroundColor: '#48BBEC',
- alignSelf: 'stretch',
- justifyContent: 'center'
- },
- buttonText: {
- alignSelf: 'center',
- },
- instructions: {
- textAlign: 'center',
- color: '#333333',
- marginBottom: 5,
- }
-});
+React.AppRegistry.registerComponent('ReactExample', () => TodoApp);