question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Android AsyncStorage: "Error restoring state" for large datasets

See original GitHub issue

This library has been working perfectly for me with smaller size state trees, but trying to use it on bigger ones I’m running into these errors when relaunching the app:

10:39:16 redux-persist/getStoredState: Error restoring data for key: entities {}

10:39:18 Possible Unhandled Promise Rejection (id: 0):
Couldn't read row 0, col 0 from CursorWindow.  Make sure the Cursor is initialized correctly before accessing data from it.

Specifically, I’m trying to store a lot of data from a server locally. To give an idea of the size, running JSON.stringify(payload).length gives 2368916, so it looks like it should be within the 6MB limit.

I’m not having any of the performance issues described in #185 either - the app runs fairly smoothly (perhaps because writes are used sparingly). It’s just a case of closing the app and reopening it leading to this error when it tries to rehydrate.

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:15 (4 by maintainers)

github_iconTop GitHub Comments

25reactions
robwalkercocommented, Apr 7, 2017

@kenma9123 I’ve worked around this issue by creating my own storage for Android that uses the filesystem rather that AsyncStorage.

Hopefully that will help others with this same issue. Perhaps there would be a way to integrate the storage implementation back into redux-persist so as to provide a more robust React Native Android storage solution?

Expand to see the code
/**
* @flow
*/

import RNFetchBlob from 'react-native-fetch-blob'

const DocumentDir = RNFetchBlob.fs.dirs.DocumentDir
const storagePath = `${DocumentDir}/persistStore`
const encoding = 'utf8'

const toFileName = (name: string) => name.split(':').join('-')
const fromFileName = (name: string) => name.split('-').join(':')

const pathForKey = (key: string) => `${storagePath}/${toFileName(key)}`

const AndroidFileStorage = {
  setItem: (
    key: string,
    value: string,
    callback?: ?(error: ?Error) => void,
  ) =>
    new Promise((resolve, reject) =>
      RNFetchBlob.fs.writeFile(pathForKey(key), value, encoding)
        .then(() => {
          if (callback) {
            callback()
          }
          resolve()
        })
        .catch(error => {
          if (callback) {
            callback(error && error)
          }
          reject(error)
        })
  ),
  getItem: (
    key: string,
    callback?: ?(error: ?Error, result: ?string) => void
  ) =>
    new Promise((resolve, reject) =>
      RNFetchBlob.fs.readFile(pathForKey(toFileName(key)), encoding)
        .then(data => {
          if (callback) {
            callback(null, data)
          }
          resolve(data)
        })
        .catch(error => {
          if (callback) {
            callback(error)
          }
          reject(error)
        })
  ),
  removeItem: (
    key: string,
    callback?: ?(error: ?Error) => void,
  ) =>
    new Promise((resolve, reject) =>
      RNFetchBlob.fs.unlink(pathForKey(toFileName(key)))
        .then(() => {
          if (callback) {
            callback()
          }
          resolve()
        })
        .catch(error => {
          if (callback) {
            callback(error)
          }
          reject(error)
        })
  ),
  getAllKeys: (
    callback?: ?(error: ?Error, keys: ?Array<string>) => void,
  ) =>
    new Promise((resolve, reject) =>
      RNFetchBlob.fs.exists(storagePath)
      .then(exists =>
        exists ? Promise.resolve() : RNFetchBlob.fs.mkdir(storagePath)
      )
      .then(() =>
        RNFetchBlob.fs.ls(storagePath)
          .then(files => files.map(file => fromFileName(file)))
          .then(files => {
            if (callback) {
              callback(null, files)
            }
            resolve(files)
          })
      )
      .catch(error => {
        if (callback) {
          callback(error)
        }
        reject(error)
      })
  ),
}

export default AndroidFileStorage
19reactions
robwalkercocommented, Apr 10, 2017

@kenma9123 I’ve created a project on npm with a cleaned up version of the above code. Check out https://www.npmjs.com/package/redux-persist-filesystem-storage

Read more comments on GitHub >

github_iconTop Results From Across the Web

redux-persist/getStoredState: Error restoring data for key: xxxxx
Make sure the Cursor is initialized correctly before accessing data from it. I've tried things like this in MainApplication.java - onCreate ...
Read more >
Advanced topics on caching in Apollo Client
To get started, pass your cache and a storage provider to persistCache . By default, the contents of your cache are immediately restored...
Read more >
React Native AsyncStorage - Asap developers
Asynchronous means that each of its methods returns an object that could be a Promise or an Error. It's unencrypted, so beware of...
Read more >
Using AysncStorage to Store Data in React Native - YouTube
This video demonstrates how to use the AsyncStorage package to store data offline in key-value pairs. This is a great way to store...
Read more >
SecureStore - Expo Documentation
Size limit for a value is 2048 bytes. An attempt to store larger values may fail. Currently, we print a warning when the...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found