首页 > 解决方案 > 最新版本的 react-native 和 AsyncStorage 丢失数据

问题描述

当我尝试使用 react-native 和 expo 更新我的应用程序(android/ios)时,我的数据丢失了,我不知道为什么:

旧版 :

“react-native”:“0.51.0”,“redux-persist”:“4.8.2”,

新版本 :

“redux-persist”:“4.8.2”,“react-native”:“~0.61.5”,“expo”:“^37.0.12”,

使用 expo 构建新版本

我如何持久化数据。代码在版本之间没有变化。

  useEffect(() => {
    persistStore(
      store,
      {
        storage: AsyncStorage,
        whitelist: ['data', 'data2' ],
        transforms: [
          createTransform(
            state => state,
            state => ({
              ...state,
              infosOpened: false,
            }),
            {
              whitelist: 'app',
            }
          ),
        ],
      },
      () => {
        setRehydrated(true)
      }
    )
  }, [])

AsyncStorage 是从 react-native 导入的,我将 react-native 保留在 expo 中。@react-native-community/async-storage 不兼容。

正如我在旧版本中看到的那样,数据在“数据用户”中以 SQLlite 格式 3 保存。数据似乎总是在更新版本中,但不再恢复。

我不知道从版本 51 到 61 是否有一些制动变化 react-native。我在 github 发布标签中看不到任何内容。

Edit1:好的,看来问题是RN使用RCTAsyncLocalStorage_V1文件夹和expo RCTAsyncLocalStorage。我如何用最简单的 IOS 和 Android 方法来解决这个问题?退出 expo 应用程序或添加迁移代码更好吗?

Edit2:最后我选择了带有 react-native-unimodules 的 RN 版本,这样我对路径存储没有问题,我可以使用 expo 中的一些依赖项。(https://blog.expo.io/you-can-now-use-expo-apis-in-any-react-native-app-7c3a93041331

也许正在解决的解决方案......我没有测试它

这里的另一种可能的解决方案。我也没有测试它:

https://github.com/expo/expo/issues/8220#issuecomment-656300244

标签: react-nativeexporedux-persist

解决方案


您可以在代码段中找到用于迁移的示例代码。这个片段是从 Expo 到纯 RN 的迁移。您只需要反向迁移。

import React, { Component } from 'react';
import { View, ActivityIndicator, AsyncStorage } from 'react-native';
import PropTypes from 'prop-types';
import RNFS from 'react-native-fs';

export default class WalletMigrate extends Component {
  componentDidMount() {
    this.migrateDataFromExpo();
  }

  migrationComplete() {
    console.log('Migration was successful. Exiting migration...')
    this.props.onComplete();
  }

  // Migrate Document directory from Expo
  async migrateDataFromExpo() {
    const expoDirectoryExists = await RNFS.exists(RNFS.DocumentDirectoryPath + '/ExponentExperienceData');

    if (!expoDirectoryExists) {
        console.log('Expo data was previously migrated. Exiting migration...');
      this.props.onComplete();
      return;
    }
    try {
        await RNFS.unlink(RNFS.DocumentDirectoryPath + '/RCTAsyncLocalStorage_V1')
        console.log('/RCTAsyncLocalStorage_V1 has been deleted. Continuing...')
    } catch {
        console.log('/RCTAsyncLocalStorage_V1 does not exist. Continuing...')
    }
    RNFS.copyFile(
      RNFS.DocumentDirectoryPath + '/ExponentExperienceData/%40USERNAME%2FAPPNAME/RCTAsyncLocalStorage',
      RNFS.DocumentDirectoryPath + '/RCTAsyncLocalStorage_V1',
    )
      .then(() => {
        RNFS.readDir(RNFS.DocumentDirectoryPath + '/RCTAsyncLocalStorage_V1').then(files => {
          files.forEach(file => {
            if (file.name !== 'manifest.json') {
              RNFS.readFile(file.path).then(fileContents => {
                AsyncStorage.setItem('data', fileContents)
                .then(() => {
                  RNFS.unlink(RNFS.DocumentDirectoryPath + '/ExponentExperienceData').then(() => this.migrationComplete());
                })
                .catch(() => {
                    console.log('An error was encountered when trying to delete /ExponentExperienceData. Exiting migration...');
                    this.props.onComplete();
                })
                .then(() => this.migrationComplete())
              });
            }
          });
        })
        .catch(error => {
            console.log('An error was encountered when trying to read the /RTCAsyncLocalStorage_V1 directory. Exiting migration...');
            console.log(error);
            this.props.onComplete();
        });
      })
      .catch(_error => this.props.onComplete());
  }

  render() {
    return (
      <View style={{ flex: 1, justifyContent: 'center', alignContent: 'center' }}>
        <ActivityIndicator />
      </View>
    );
  }
}

WalletMigrate.propTypes = {
  onComplete: PropTypes.func,
};


推荐阅读