The basic organization of the React Native app for Part 1/3 is shown in the Diagram below.
To summarize, the main App.js file initializes React Navigation, which references the default home screen MyBooks.js, and the additional ViewEditBook.js screen. Those two screens are populated with data from a locally stored SQLite database that is viewed and interacted with using Picker, FlatList, TextInput, and DateInput UI components.
For the rest of the article I’d like to talk about the three topics that were the least straightforward when building this app: choosing persistent storage, nuances of state management, and handling dates. The remainder of the implementation details are covered pretty well by the official react native documentation.
1. SQLITE – I’d first like to quickly address why I decided to to use SQLite for persistent storage for this app. There’s no default database suggestions in the official react native docs, though they do mention AsyncStorage for key-value persistent storage. Since storing a sortable/searchable list of books that have associated metadata and notes is a pretty standard RDBMS/SQL use case, I was leaning more towards SQL over key-value or NoSQL options like MongoDB or CouchDB. A lot of articles will suggest Firebase or Realm for the server synch and auto-scaling capabilities, but I felt the overhead for setting that up was too far of a detour from the main goal of learning some simple React Native. I ended up using react-native-sqlite-storage and it was super simple and worked great.
2. STATE – Coming from native Android development, the special State construct was perhaps the most notable concept that I was introduced to in React Native. In Android Development, the special “Activity” Java object feels like the mental anchor for the organization of an application. Activity lifecycle methods and UI listeners are used to setup and then react to user interactions with the interface. React Native feels like it is the reverse of Android in how it anchors you mentally in your application organization. Your starting unit of your application is the screen UI component, which then issues asynchronous updates to the “state”, or memory of the application. UI elements that reference the state should automatically update when that state is updated. From React.js docs (also applicable to React Native in this instance):
“Thanks to the
setState() call, React knows the state has changed, and calls the
render() method again to learn what should be on the screen. This time,
this.state.date in the
render() method will be different, and so the render output will include the updated time[screen]. React updates the DOM accordingly. “
This seems to work fine for simple cases, but when I tried to use a nonstandard Dialog Component with text input, I noticed the widget was not updating from state updates properly. Because this mechanism is “under the hood” it is difficult to troubleshoot. I ended up not needing the dialog component, but regardless I’ll be looking at Redux for state management in the future, and more advice in general on how to troubleshoot when your state isn’t causing updates correctly.
3. DATES – This last section is just a quick reminder that date input, storage, and updating should be handled carefully and deliberately, even when working on a simple proof of concept like Part 1 of this app. See four different methods of storing dates below:
Here is the source code for part 1 of this series: https://github.com/cameronvoell/mobile-book-companion/releases/tag/v1.0 and here is an additional commit where I cleaned up the dates after creating the 1.0 release: https://github.com/cameronvoell/mobile-book-companion/commit/2cf3e281d28bef887b3a4a4bfdd10584c6a961d9
Look out for Part 2/3 with Google Books API and Kindle Notes import soon! (in progress)