Re-frame and IndexedDB

From a high level of view, how can I integrate IndexDB in a re-frame single page mobile web app?
The app is a simple wizard with a lot of input fields, included several image upload. The different FileList objects of these photos are stored in re-frame’s app-db, so I can use something like GetObjecturl to show thumbnails. This wizard will be used by technicians, sometimes on places (factories) with limited internet connection. I want to prevent the wizard from losing all data of the inputs and photos.
So I am thinking to regularly make a backup of re-frame’s app-db into IndexedDB. What are the possible strategies? I was thinking something that runs every x seconds and then make a backup. Or should each event, next to updating the db, also update the IndexedDb? Wouldn’t that be slow?
Any ideas?
Thanks in advance

Or maybe another solution is to save the appdb every x seconds.
Each event that updates the app-db (like typing in an input field) also fires an event “schedule-post-data”. And that event calls js/setTimeout with x seconds timeout and of course first clearing the previous timeout. So while typing, all lot of schedule-post-data will be called. But the actual post to server would only be executed once, after x seconds.

How about Datahike in ClojureScript with IndexedDB support?


Maybe to get some inspiration, there’s a way to get your state in localStorage. (I think getting it to indexedDB should be comparable)

What I do to get this effect, is use handler middleware I apply to some handlers that just save the complete state or a subset of it

ie. use a re-frame middleware like:

(def local-storage-persist-interceptor
   :id :system.local-storage/interceptor
   :after (fn [context]
             (persist-db-to-local-storage (:db (:effects context)))
1 Like

Thanks simongray, I’ll have a look at it.

Thanks for the info Kah0ona. What about events attached to onChange of a text input? Wouldn’t they trigger a lot of persist-db-to-local-storage? Like after each character is typed in the input field.
EDIT : after looking into the source of storage-atom I found out it has some nice debounce and delay functionality which solves my problem

There is a very popular JS library called localForage, which has a local-storage-like API for interacting with IndexedDB. You can easily interop with it from CLJS. Also, instead of updating the state on every on-change event, it may be better to update when the input has been blurred / loses focus (i.e. via the on-blur event).


yes, but, you can apply middleware on SOME handlers.

  (fn [db _] ,,,))

So use that tactically.

And yes, that storage atom lib does some clever stuff; but I prefer to have a bit of control when to persist.