Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Native computational heavy task

Very simple and common use case, but I can't find satisfying answer. I have react native app which needs to store some data locally. I am using redux and redux-observables and Realm as a storage.

What I need is: some action occur, let's say ADD_ITEM. I need to update UI with some payload (standard redux). Then I want to create/transform that payload to another piece of data and save that data into Realm (asynchronously). Whatever I try, it always lags UI (a lot).

I tried to wrap that realm call into promise and use switchMap, but it's still slow.

I haven't took a look at workers yet but they only accept strings, which is let's say much less usable for me.

I can offload completely that computation to native background thread but that will be very uncomfortable and a lot of writing.

Could async await help me? Of redux-saga? I feel like it's the same thing, not real async processing.

Or am I using completely wrong libraries for this?

const insertOrderItem = (action$) =>
    action$.ofType(Action.ADD_ORDER_ITEM)
        .switchMap(({ payload }) => Rx.Observable.fromPromise(
            new Promise((resolve, reject) => {
                storage.insert(createObject(payload)
                resolve({
                    type: "OPERATION_ADDED"
                })
            })
        ))

In general, storing small piece of data to realm shouldn't be THAT much computational heavy but I feel like it's necessary to do this kind of jobs on background thread.

Am I missing something?

Thanks

like image 664
trubi Avatar asked Mar 14 '17 15:03

trubi


1 Answers

I had same problem with my app using React Native + Realm DB. I tried all ways without having to write native code and make the bridge from react-native to native, and finally I found a solution:

https://corbt.com/posts/2015/12/22/breaking-up-heavy-processing-in-react-native.html

  1. Install npm install next-frame --save.
  2. Add next-frame to your code import nextFrame from 'next-frame';
  3. Add this line within a for that took long, or a for which insert in DB await nextFrame();

A complete example would look like this:

import nextFrame from 'next-frame';

let response = await fetch("https://emberall.com/user/1/recordings");
let responseJSON = await response.json();

for (let recording of responseJSON.recordings) {
  await nextFrame(); // The javascript will yield here and not resume execution until the next frame. 
  mergeRecordingToLocalDatabase(recording);
}

Basically what this does is that in every iteration or db-insert it waits for JS to render and process next UI frame, so your app will not get stuck or freeze.

P.D.: I know months have passed since question but I think a lot o people could benefit from this.

like image 191
leo7r Avatar answered Sep 18 '22 08:09

leo7r