Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Offline support for React Native App

I am looking to add offline support to a React Native application. The app currently runs off an API that is backed by a Postgres db.

I am already using NetInfo to determine whether a user has a connection or not but am looking to understand the best way to add offline capabilities where a user can continue to update their data and information and then just have everything sync when they get a connection again.

It seems like a pouchdb/couchdb solution is often recommended - however, I don't want to change my database at all. Ideally, I'd love to have some sort of way to store "jobs" of API calls in a queue and then execute them once connection is restored.

What is the best way to go about getting this offline functionality on a React Native App.

Thanks in advance!

like image 963
Karim Avatar asked May 16 '16 04:05

Karim


1 Answers

You may use e.g. redux for data storage in general. Assuming you have a LOAD_POSTS_DATA action, which a component may fire at a point of time you may use a a reducer like this:

export const LOAD_POSTS_DATA = 'LOAD_POSTS_DATA';
var connected = ... // filled by NetInfo

const initialState = {
  data: [],
};

export default function reducer(state = initialState, action) {
  switch (action.type) {
    case LOAD_POSTS_DATA:
      if (connected) {
        return {
          open: true,
        };  
      } 

      return state;

    default:
      return state;
  }
}

export function load() {
  return {
    type: LOAD_POSTS_DATA,
  };
}

This would only not load the data, for the deferring you would write a second reducer like this:

const CLEAR_QUEUE = 'CLEAR_QUEUE';
import { LOAD_POSTS_DATA } from './otherReducer';
var connected = ... // filled by NetInfo

const initialState = {
  queue: [],
};

export default function reducer(state = initialState, action) {
  switch (action.type) {
    case LOAD_POSTS_DATA:
      if (!connected) {
        var q = state.queue;
        q.push(action);

        return {
          queue: q,
        };  
      } 

      return state;

    case CLEAR_QUEUE:
      return {
        queue: []
      }

    default:
      return state;
  }
}

// needs to be called as soon as you go back only
// requires redux-thunk
export function getOperations() {
  return (dispatch, getState) => {
    const { thisReducer: { queue } } = getState();
    queue.forEach(action => dispatch(action));

    return {
      type: CLEAR_QUEUE,
    };
  };
}

The second one stores every deferrable action (needs to be imported from other reducers) and uses redux-thunk to get hold of the actions and dispatch them as soon as you are back online.

like image 168
Daniel Schmidt Avatar answered Jan 03 '23 12:01

Daniel Schmidt