Slide 1

Slide 1 text

O!ine First React Native Connect.Tech 2019

Slide 2

Slide 2 text

Tim Whitacre Atlanta Engineering Manager @ New Story Charity ✨ @timwco ✨ @newstorycharity

Slide 3

Slide 3 text

We pioneer solutions to end global homelessness. newstorycharity.org

Slide 4

Slide 4 text

O!ine First

Slide 5

Slide 5 text

O!ine first is an approach to software development in which developers build an application's core features to function with or without an internet connection. ... This is especially important for end users who travel and experience internet coverage blind spots. 1 1 https://whatis.techtarget.com/definition/o"ine-first

Slide 6

Slide 6 text

Why O!ine First » Connected & Powered => Disconnected & Battery » Geography plays an important role » O!ine is simply a fact of life. !

Slide 7

Slide 7 text

Why Now? When else are you going to think about it?

Slide 8

Slide 8 text

Benefits » Avoid Local Data Loss » Speed Up Your App » Your App Runs Everywhere

Slide 9

Slide 9 text

Pitfalls » Data Conflicts » Diverse Data Types » Implementation Time » Others 2 2 https://alistapart.com/article/o"ine-first

Slide 10

Slide 10 text

O!ine Syncing Options » Real Time » Data Syncs Upon Connection » Progressive Enhancement » Manual » Manually preform a sync operation » Architecture Strategy

Slide 11

Slide 11 text

O!ine first requires a mix of UX and Development Strategies. This includes both frontend and backend solutions.

Slide 12

Slide 12 text

Please don't skip the UX part.

Slide 13

Slide 13 text

How Do O!ine Apps Work?

Slide 14

Slide 14 text

Local Storage !

Slide 15

Slide 15 text

{ org_1234: { app_status: { last_upload: '2019-09-03T20:59:05+00:00' }, admin_user: { name: 'Stacy', token: 'ABCDEF123456' }, data: { ... } }, org_5678: { app_status: { last_upload: '2019-10-17T21:33:01+00:00' }, admin_user: { name: 'Ikenna', token: 'HIJKLMNO789' }, data: { ... } } } See a potential problem...?

Slide 16

Slide 16 text

O!ine Tools » GraphQL » Redux O!ine/Persist » Realm

Slide 17

Slide 17 text

GraphQL Only get the data that we need. Less queries, less operations and quicker access to data.

Slide 18

Slide 18 text

export const SYNC_DOWNLOAD = gql` query Download($lastSyncedAt: ISO8601DateTime) { posts(lastSyncedAt: $lastSyncedAt) { id title content comments { id content } } authors(lastSyncedAt: $lastSyncedAt) { id first_name last_name } categories(lastSyncedAt: $lastSyncedAt) { id title } } `;

Slide 19

Slide 19 text

Redux O!ine/Persist Redux O!ine allows us to store and "rehydrate" our state as needed.

Slide 20

Slide 20 text

// Store Configure import { createStore, applyMiddleware, compose } from 'redux'; import { persistStore, persistReducer } from 'redux-persist'; import storage from 'redux-persist/lib/storage'; import { createOffline } from '@redux-offline/redux-offline'; import offlineConfig from '@redux-offline/redux-offline/lib/defaults'; import reducers from './reducers'; const { middleware, enhanceReducer, enhanceStore } = createOffline({ ...offlineConfig, persist: false }); export default key => { const persistConfig = { key, storage, blacklist: ['offline', 'user'] }; const persistedReducer = persistReducer(persistConfig, enhanceReducer(reducers)); const store = createStore( persistedReducer, compose( enhanceStore, applyMiddleware(middleware))); const persistor = persistStore(store); return { store, persistor }; };

Slide 21

Slide 21 text

// App.js import { Provider as ReduxProvider } from 'react-redux'; import { PersistGate } from 'redux-persist/integration/react'; import configureStore from 'utilities/configure-store'; class App extends Component { render () { const orgId = getOrganizationId(); const { store, persistor } = configureStore(orgId); return ( // Standard Redux Provider // Delays rendering of app ); } }

Slide 22

Slide 22 text

Realm Realm Database is a fast, easy to use, and open source alternative to SQLite and Core Data. » Mobile First » Simple API, Define Schemas » Faster than SQLite » Lazy Queries » Data Migrations !

Slide 23

Slide 23 text

// Realm Models // models.js const PostSchema = { name: 'Post', properties: { title: 'string', content: 'string', comments: 'Comment[]', tags: 'Tag[]', categories: 'Category[]', author: 'Author', } }; const CommentSchema = { name: 'Comment', properties: { author: 'Author', comment: 'string', approved: 'bool' } }; // Tag Schema // Author Schema // Category Schema

Slide 24

Slide 24 text

// Realm Setup // realm-setup.js import models from './db/models'; // { Posts, Comments, Tags, Categories } const database = async (orgId, schemaVersion) => { if (orgId === 'guest') return null; // If no user, no need for a database const schema = Object.values(models); const config = { schema, path: `${orgId}.realm`, schemaVersion }; return await Realm.open(config); };

Slide 25

Slide 25 text

// App.js import realmSetup from 'utilities/realm-setup'; // Import Realm class App extends Component { render () { const schemaVersion = 1; const orgId = getOrganizationId(); const realm = realmSetup(orgId, schemaVersion); return ( ); } }

Slide 26

Slide 26 text

Realm Queries // Basic Query const posts = realm.objects('Post'); posts.forEach(p => console.log(p.title)); // Posts Sorted Alphabetically const sortedPosts = posts.sorted('title'); // Specific Query (Comments Are Approved) const comments = realm.objects('Comment'); const posts_comments = comments.filtered('approved = true');

Slide 27

Slide 27 text

Realm Writes // New Comment const author = realm.objectForPrimaryKey('Author', 1); const newComment = { author, comment: 'Offline is really cool' }; // Create On it's Own realm.write(() => realm.create('Comment', newComment)); // Create with Relationship const post = realm.objectForPrimaryKey('Post', 291); try { realm.write(() => { post.comments.push(newComment)}); } catch (e) { console.log('Error Upon Creation'); }

Slide 28

Slide 28 text

Pitfalls » Maintenance (Active Development) » Dependency & Upgrades

Slide 29

Slide 29 text

Review » UX/UI Strategy » Local Data Loss (Realm) » Global State Persistence (Redux O!ine/Persist) » Diverse Data Types (Realm, GraphQL) » Data Conflicts (Realm, GraphQL)

Slide 30

Slide 30 text

Thank You ! l.timw.co/ctech2019 ✨ @timwco ✨ @newstorycharity

Slide 31

Slide 31 text

Image Credits » Devopedia » @andreee » New Story Charity