OFFLINE FIRST
REACT NATIVE

ABOUT ME

Shawn McKay

Semios Mobile

Real time sensor data/graphs.

Make field notes.

OFFLINE

FIRST

Title Text

OFFLINE

          LAST

FIRST

Offline Last

displaying the connection

lazy / eager loading

persistant data

handling large files

read / write responses

a better solution

 

C?NN?CT?D?

Causes

 

No connection

Poor connection

Not Found

Blocked

Subtitle

Tell Your Users Why
Things Aren't Working

Error Codes

Try Again

503 - Server error

504 - Timeout

 

Give Up

404 - Not Found

451 - Unavailable for legal reasons

Subtitle

Connection Detection

<Page />

import { View, StatusBar } from 'react-native';
import OfflineBanner from './OfflineBanner';
 

const Page = ({ children, style }) => (

  <View style={[styles.navContentView, style]}>

    <StatusBar

      backgroundColor="transparent"

      translucent barStyle="light-content"

    />

    <OfflineBanner />

    {React.Children.toArray(children)}

  </View>

)

<OfflineBanner />

const OfflineBanner = ({ netInfo }) => {
 return (
   netInfo === 'none'
    ? <Code />
    : null;
  );
};

const mapState = state => ({
  netInfo: state.netInfo,
});

export default connect(mapState)(NetInfo);

Connection

Is Not Binary

LAZY       EAGER

A) load data when needed

B) load most data upfront

A) load data when needed

B) load most data upfront

C) b, then background sync a

A) load data when needed

B) load most data upfront

C) b, then background sync a

D) (b or c) + persist data

BE PERSISTANT

3 Storage Options

key/val

state

database

Redux Persist

 

 

 

NOTE: Github has an

'X-Frame-Options: deny'

HTTP header

Meta Data + Photos

Large Data +

Poor Connection

=

UPLOADING PHOTOS

UPLOADING
FORM DATA

upload as multi-part with
RN-fetch-blob

 

UPLOADING
LARGE FILES

sync meta data first,
larger files last

READ

WRITE

READ = CACHE

requests

images

RN-cached-image

WRITE

Not as easy...

offline user clicks:
A) 

B) 136
C) 137
D) throw error

OPTIMISTIC ||
PESSIMISTC UI

Thunk

const async = () => (dispatch) => {

  dispatch({ type: 'PENDING' })

  fetch(someURL)

    .then((data) => dispatch({ type: 'SUCCESS' }))

    .catch((e) => dispatch({ type: 'FAILURE' }))

}

+1

Pessimistic

+1

Optimistic

-1

In a perfect world...

DO

SOMETHING

HERE

ALL IN ONE

OFFLINE

REDUX OFFLINE

=

connection detection
+

redux-persist

+

redux-optimistic-ui

+

retry/rollback

RETRY STRATEGY

Time

RETRY STRATEGY

const decaySchedule = [

1000, //After 1 seconds

1000 * 5, //After 5 seconds

1000 * 15, //After 15 seconds

1000 * 30, //After 30 seconds

1000 * 60, //After 1 minute

1000 * 60 * 3, //After 3 minutes

1000 * 60 * 5, //After 5 minutes

1000 * 60 * 10, //After 10 minutes

1000 * 60 * 30, //After 30 minutes

1000 * 60 * 60 //After 1 hour ];

export default (action, retries): => decaySchedule[retries];

CUSTOM RETRY

const config = {
  retry: (action, retries) =>
    action.meta.urgent
      ? 100
      : 1000 * (retries + 1)
}

A DIFFERENT
ASYNC MODEL

Thunk

const async = () => (dispatch, getState) => {

  dispatch({ type: 'LOADING' })

  fetch(someURL)

    .then((data) => dispatch({ type: 'SUCCESS' }))

    .catch((e) => dispatch({ type: 'FAILURE' }))

}

Redux-Offline

const asyncAction = () => ({

  type: 'LOADING',

  meta: {

    offline: {

      effect: { url: someURL },

      commit: { type: 'SUCCESS' },

      rollback: { type: 'FAILURE' },

    }

  }

})

Redux-Offline

const asyncAction = (id) => ({

  type: 'LOADING',

  meta: {

    offline: {

      effect: { url: `${someURL}/${id}` },

      commit: { type: 'SUCCESS', payload: { id }},

      rollback: { type: 'FAILURE', payload: { id } },

    }

  }

})

No Middleware Actions

const asyncAction = (id) => ({

  type: 'LOADING',

  meta: {

    offline: {

      effect: { url: `${someURL}/${id}` },

      commit: () => (dispatch) => dispatch(success()),

      rollback: { type: 'FAILURE', payload: { id } },

    }

  }

})

Redux-Offline can get better...

Actions w/ middleware

Background sync

Immutable data

"How can I make it?"

     Average Programmer

"How can I break it?"

     Awesome Programmer

Plan for EVERYTHING

to go wrong. always.
Thanks.


@Sh_McK

shawn.j.mckay@gmail.com

OFFLINE FIRST REACT NATIVE

By Shawn McKay

OFFLINE FIRST REACT NATIVE

  • 1,568