我在React Native领域还是个新手,通常在移动/本地领域也是如此,我发现文档在数据持久性方面有点缺乏。

我在React Native中存储数据的选项是什么,每种类型的含义是什么?例如,我看到有本地存储和异步存储,但我也看到了Realm之类的东西,我很困惑所有这些如何与外部数据库一起工作。

我特别想知道:

数据持久性有哪些不同的选项? 对于每一个,持久性的限制是什么(即,何时数据不再可用)?例如:关闭应用程序时,重启手机时等。 对于每一个,在iOS和Android上的实现有区别吗(除了一般设置)? 离线访问数据的选项比较如何?(或者离线访问通常是如何处理的?) 还有其他需要我考虑的问题吗?

谢谢你的帮助!


快速和肮脏:只需使用Redux + react-redux + Redux -persist + AsyncStorage for react-native。

它几乎完美地适合react本机世界,工作就像一个迷人的android和ios。此外,它还有一个坚实的社区,以及大量的信息。

有关工作示例,请参阅Facebook上的F8App。

数据持久性有哪些不同的选项?

对于react native,您可能希望使用redux和redux-persist。它可以使用多个存储引擎。AsyncStorage和redux- persistent - filessystem -storage是RN的选项。

还有其他选项,如Firebase或Realm,但我从未在RN项目中使用过它们。

对于每一个,持久性的限制是什么(即,何时数据不再可用)?例如:关闭应用程序时,重启手机时等。

使用redux + redux-persist,可以定义哪些是持久化的,哪些不是。如果没有持久化,则数据在应用程序运行时存在。当持久化时,数据在应用程序执行(关闭,打开,重启手机等)之间持久化。

AsyncStorage在Android上的默认限制为6MB。可以配置一个更大的限制(在Java代码上)或使用redux- persistent - filessystem -storage作为Android的存储引擎。

对于每一个,在iOS和Android上的实现有区别吗(除了一般设置)?

使用redux + redux-persist + AsyncStorage在android和iOS上的设置完全相同。

离线访问数据的选项比较如何?(或者离线访问通常是如何处理的?)

使用redux,离线访问几乎是自动的,这要归功于它的设计部分(动作创建者和还原器)。

您获取和存储的所有数据都是可用的,您可以轻松地存储额外的数据来指示状态(获取,成功,错误)和获取时间。通常,请求获取不会使旧数据失效,您的组件只是在接收到新数据时进行更新。

反之亦然。你可以存储数据,你正在发送到服务器,仍然悬而未决,并相应处理它。

还有其他需要我考虑的问题吗?

React提倡一种反应式的创建应用的方式,Redux非常适合它。你应该在使用常规Android或iOS应用程序中使用的选项之前尝试一下。此外,你会找到更多关于这些的文档和帮助。

上面提到的是正确的存储方法,不过如果你还需要考虑需要存储的任何PII数据,那么你也可以使用https://github.com/oblador/react-native-keychain之类的东西将其隐藏到keychain中,因为ASyncStorage是未加密的。它可以作为redux-persist之类的持久化配置的一部分应用。

以下是我在决定推进当前应用项目的最佳方式时所学到的。

异步存储(以前是React Native的“内置”,现在自己移动)

我在生产应用中使用AsyncStorage。存储保持在设备本地,是未加密的(在另一个答案中提到),如果你删除应用,存储就会消失,但应该保存为设备备份的一部分,并在升级期间持续存在(包括通过TestFlight进行的本地升级和通过CodePush进行的代码升级)。

结论:本地存储;您提供自己的同步/备份解决方案。

SQLite

我参与的其他项目使用sqlite3作为应用程序存储。这为您提供了一种类似sql的体验,可压缩的数据库也可以在设备之间传输。我没有任何将它们同步到后端的经验,但我猜想存在各种各样的库。有用于连接到SQLite的RN库。

数据以传统的数据库格式存储,数据库、表、键、索引等都以二进制格式保存到磁盘上。可以通过命令行或具有SQLite驱动程序的应用程序直接访问数据。

结论:本地存储;您提供同步和备份。

重火力点

Firebase offers, among other things, a real time noSQL database along with a JSON document store (like MongoDB) meant for keeping from 1 to n number of clients synchronized. The docs talk about offline persistence, but only for native code (Swift/Obj-C, Java). Google's own JavaScript option ("Web") which is used by React Native does not provide a cached storage option (see 2/18 update below). The library is written with the assumption that a web browser is going to be connecting, and so there will be a semi-persistent connection. You could probably write a local caching mechanism to supplement the Firebase storage calls, or you could write a bridge between the native libraries and React Native.

更新2/2018 我已经找到了React Native Firebase,它提供了一个兼容的JavaScript接口到本地iOS和Android库(做什么谷歌可能可以/应该做),给你所有的好东西的本地库与React Native支持的奖励。谷歌除了实时数据库之外还引入了JSON文档存储,因此对于我计划构建的一些实时应用程序,我将重新审视Firebase。

实时数据库存储为类似json的树,您可以在网站上编辑和导入/导出非常简单。

结论:使用react-native-firebase, RN可以获得与Swift和Java相同的好处。[/update]适合网络连接设备。低成本低利用率。与其他谷歌云产品很好地结合。数据很容易看到和编辑从他们的界面。

领域

更新4/2020 MongoDB已经收购了Realm,并计划将其与MongoDB Stitch(下文将讨论)结合起来。这看起来很令人兴奋。

更新9/2020 使用Realm vs. Stitch: Stitch API本质上允许JS应用程序(React Native或web)直接与Mongo数据库对话,而不是通过您自己构建的API服务器。

Realm旨在在发生更改时同步数据库的各个部分。

这两者的结合有点令人困惑。以前被称为stitch的API仍然像你传统的Mongo查询和更新调用一样工作,而较新的Realm的东西附加到代码中的对象,并自行处理同步…主要是。我还在研究一个项目的正确方法,那就是使用SwiftUI,所以这有点离题。尽管如此,还是很有前途的。


同时也是一个具有自动网络同步的实时对象存储。他们标榜自己是“设备优先”,演示视频展示了设备如何处理零星或丢失的网络连接。

他们提供对象存储的免费版本,您可以在自己的服务器上或AWS或Azure等云解决方案中托管。您还可以创建不持久化在设备上的内存存储、不与服务器同步的仅设备存储、只读服务器存储以及用于跨一个或多个设备同步的完整读写选项。他们有专业的和企业的选择,每个月的预付费用比Firebase更高。

与Firebase不同,React Native和Xamarin支持所有Realm功能,就像Swift/ObjC/Java(本地)应用程序一样。

数据绑定到代码中的对象。因为它们是已定义的对象,所以您确实有一个模式,并且版本控制是代码正常运行的必要条件。通过Realm提供的GUI工具可以直接访问。设备上的数据文件跨平台兼容。

结论:设备优先,可选同步免费和付费计划。React Native支持的所有特性。横向扩展比Firebase更昂贵。

iCloud

老实说,我还没有做很多玩这个,但在不久的将来会这样做。

如果你有一个使用CloudKit的本地应用程序,你可以使用CloudKit JS从web应用程序(或者,在我们的情况下,React native)连接到你的应用程序的容器。在这种情况下,你可能会有一个原生iOS应用程序和一个React native Android应用程序。

和Realm一样,它在本地存储数据,并尽可能将数据同步到iCloud。你的应用程序有公共商店,每个客户有私人商店。客户甚至可以选择与其他用户共享他们的商店或对象。

我不知道获取原始数据有多容易;模式可以在苹果网站上建立。

结论:非常适合苹果应用。

Couchbase

有很多大公司在背后支持。有一个社区版和企业版的标准支持成本。

他们的网站上有一个教程,是关于如何连接React Native的。我在这方面也没有花太多时间,但就功能而言,它看起来是Realm的可行替代方案。我不知道在你的应用程序或你构建的任何api之外获取你的数据有多容易。

[编辑:发现了一个关于Couchbase和CouchDB的旧链接,CouchDB可能是另一个可以考虑的选项。这两者在历史上是相关的,但目前完全不同的产品。请看这个比较。

结论:看起来有类似领域的能力。可以仅用于设备,也可以同步。我需要试试。

MongoDB

更新4/2020

Mongo收购了Realm,并计划将MongoDB Stitch(下面讨论)与Realm(上面讨论)结合起来。


我正在使用这个服务器端应用程序的一部分,在本地使用AsyncStorage。我喜欢所有东西都存储为JSON对象,使得传输到客户端设备非常简单。在我的用例中,它被用作电视指南数据的上游提供者和我的客户端设备之间的缓存。

数据没有像模式那样的硬结构,因此每个对象都存储为易于搜索、过滤等的“文档”。类似的JSON对象可以有额外的(但不同的)属性或子对象,允许在如何构造对象/数据方面有很大的灵活性。

我没有尝试过任何客户端到服务器同步特性,也没有嵌入式使用过它。MongoDB的React Native代码确实存在。

结论:只有本地NoSQL解决方案,没有像Realm或Firebase这样明显的同步选项。

更新2/2019

MongoDB有一个“产品”(或服务)叫做Stitch。因为客户端(在网络浏览器和手机的意义上)不应该直接与MongoDB对话(这是通过服务器上的代码完成的),他们创建了一个无服务器前端,你的应用程序可以与之交互,如果你选择使用他们的托管解决方案(Atlas)。他们的文档显示有一个可能的同步选项。

这篇2018年12月的文章讨论了在一个示例应用程序中使用React Native、Stitch和MongoDB,并在文档中链接了其他示例(https://www.mongodb.com/blog/post/building-ios-and-android-apps-with-the-mongodb-stitch-react-native-sdk)。

Twilio同步

另一个用于同步的NoSQL选项是Twilio的Sync。从他们的网站: “同步可以让你在任意数量的设备上实时管理状态,而无需处理任何后端基础设施。”

我将其视为Firebase的替代方案,特别是在与两个团队交谈后。我也喜欢他们的其他通讯工具,用它们在一个简单的网页应用上发短信更新。


[编辑]自从我最初写这篇文章以来,我花了一些时间和Realm在一起。我喜欢我不需要写一个API来同步应用程序和服务器之间的数据,类似于Firebase。无服务器函数对于这两者也很有帮助,可以限制我必须编写的后端代码的数量。

我喜欢MongoDB数据存储的灵活性,因此它成为了我在基于web和其他需要连接的应用程序的服务器端的选择。

我找到了RESTHeart,它为MongoDB创建了一个非常简单、可扩展的RESTful API。构建一个React (Native)组件来读取和写入JSON对象到RESTHeart,然后RESTHeart将它们传递给/从MongoDB。


[编辑]我添加了关于如何存储数据的信息。有时,如果您必须调整和测试数据,那么了解您在开发和测试期间可能要做多少工作是很重要的。


在过去的一年(2018年)设计一个高并发项目时,我尝试了其中几个选项。他们中的一些人在他们的文档中提到了硬并发和软并发限制(我相信Firebase有一个10,000个连接的硬限制,而Twilio的是一个软限制,根据与两个团队在AltConf上的讨论)。

如果你正在设计一款面向数万至数十万用户的应用,那么就要准备好相应地扩展数据后端。

我们不需要redux-persist,我们可以简单地使用redux持久化。

react-redux + AsyncStorage = redux-persist

在createsotre文件中添加这些行

store.subscribe(async()=> await AsyncStorage.setItem("store", JSON.stringify(store.getState())))

这将在redux存储中有一些变化时更新AsyncStorage。

然后加载json转换的存储。当应用程序加载。并重新设置存储。

因为还原-坚持在使用wix react-native-navigation时会产生问题。如果是这种情况,那么我更喜欢使用简单的redux与上述订阅功能

您可以使用比异步存储更容易使用的同步存储。 这个库很棒,它使用异步存储来异步保存数据,并使用内存来立即同步加载和保存数据,所以我们将数据异步保存到内存中,并在应用程序同步中使用,这很棒。

import SyncStorage from 'sync-storage';

SyncStorage.set('foo', 'bar');
const result = SyncStorage.get('foo');
console.log(result); // 'bar'

如果你想管理复杂的数据类型,你可以使用Realm或Sqlite。

否则,使用内置的react native asynstorage