refactor(react-native-github): remove AsyncStorage from JS

Summary:
## Changelog
[JS][Removed] - Removed AsyncStorage module from react-native

Reviewed By: NickGerleman

Differential Revision: D40302352

fbshipit-source-id: 9377ea12036e498dde0b4b0f56de5c4fb9bd2461
This commit is contained in:
Ruslan Lesiutin
2022-10-31 14:39:19 -07:00
committed by Facebook GitHub Bot
parent 4de2aaba50
commit 20eeb1bfe3
9 changed files with 15 additions and 870 deletions
-261
View File
@@ -1,261 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow
*/
'use strict';
const React = require('react');
const ReactNative = require('react-native');
const {AsyncStorage, Text, View, StyleSheet} = ReactNative;
const {TestModule} = ReactNative.NativeModules;
const deepDiffer = require('react-native/Libraries/Utilities/differ/deepDiffer');
const nullthrows = require('nullthrows');
const DEBUG = false;
const KEY_1 = 'key_1';
const VAL_1 = 'val_1';
const KEY_2 = 'key_2';
const VAL_2 = 'val_2';
const KEY_MERGE = 'key_merge';
const VAL_MERGE_1 = {foo: 1, bar: {hoo: 1, boo: 1}, moo: {a: 3}};
const VAL_MERGE_2 = {bar: {hoo: 2}, baz: 2, moo: {a: 3}};
const VAL_MERGE_EXPECT = {foo: 1, bar: {hoo: 2, boo: 1}, baz: 2, moo: {a: 3}};
// setup in componentDidMount
let done = (result: ?boolean) => {};
let updateMessage = (message: string) => {};
function runTestCase(description: string, fn: () => void) {
updateMessage(description);
fn();
}
function expectTrue(condition: boolean, message: string) {
if (!condition) {
throw new Error(message);
}
}
// Type-safe wrapper around JSON.stringify
function stringify(
value:
| void
| null
| string
| number
| boolean
| {...}
| $ReadOnlyArray<mixed>,
): string {
if (typeof value === 'undefined') {
return 'undefined';
}
return JSON.stringify(value);
}
function expectEqual(
lhs: ?(any | string | Array<Array<string>>),
rhs:
| null
| string
| {
bar: {boo: number, hoo: number},
baz: number,
foo: number,
moo: {a: number},
}
| Array<Array<string>>,
testname: string,
) {
expectTrue(
!deepDiffer(lhs, rhs),
'Error in test ' +
testname +
': expected\n' +
stringify(rhs) +
'\ngot\n' +
stringify(lhs),
);
}
function expectAsyncNoError(
place: string,
err: ?(Error | string | Array<Error>),
) {
if (err instanceof Error) {
err = err.message;
}
expectTrue(
err === null,
'Unexpected error in ' + place + ': ' + stringify(err),
);
}
function testSetAndGet() {
AsyncStorage.setItem(KEY_1, VAL_1, err1 => {
expectAsyncNoError('testSetAndGet/setItem', err1);
AsyncStorage.getItem(KEY_1, (err2, result) => {
expectAsyncNoError('testSetAndGet/getItem', err2);
expectEqual(result, VAL_1, 'testSetAndGet setItem');
updateMessage('get(key_1) correctly returned ' + String(result));
runTestCase('should get null for missing key', testMissingGet);
});
});
}
function testMissingGet() {
AsyncStorage.getItem(KEY_2, (err, result) => {
expectAsyncNoError('testMissingGet/setItem', err);
expectEqual(result, null, 'testMissingGet');
updateMessage('missing get(key_2) correctly returned ' + String(result));
runTestCase('check set twice results in a single key', testSetTwice);
});
}
function testSetTwice() {
AsyncStorage.setItem(KEY_1, VAL_1, () => {
AsyncStorage.setItem(KEY_1, VAL_1, () => {
AsyncStorage.getItem(KEY_1, (err, result) => {
expectAsyncNoError('testSetTwice/setItem', err);
expectEqual(result, VAL_1, 'testSetTwice');
updateMessage('setTwice worked as expected');
runTestCase('test removeItem', testRemoveItem);
});
});
});
}
function testRemoveItem() {
AsyncStorage.setItem(KEY_1, VAL_1, () => {
AsyncStorage.setItem(KEY_2, VAL_2, () => {
AsyncStorage.getAllKeys((err, result) => {
expectAsyncNoError('testRemoveItem/getAllKeys', err);
expectTrue(
nullthrows(result).indexOf(KEY_1) >= 0 &&
nullthrows(result).indexOf(KEY_2) >= 0,
'Missing KEY_1 or KEY_2 in ' + '(' + nullthrows(result).join() + ')',
);
updateMessage('testRemoveItem - add two items');
AsyncStorage.removeItem(KEY_1, err2 => {
expectAsyncNoError('testRemoveItem/removeItem', err2);
updateMessage('delete successful ');
AsyncStorage.getItem(KEY_1, (err3, result2) => {
expectAsyncNoError('testRemoveItem/getItem', err3);
expectEqual(
result2,
null,
'testRemoveItem: key_1 present after delete',
);
updateMessage('key properly removed ');
AsyncStorage.getAllKeys((err4, result3) => {
expectAsyncNoError('testRemoveItem/getAllKeys', err4);
expectTrue(
nullthrows(result3).indexOf(KEY_1) === -1,
'Unexpected: KEY_1 present in ' + nullthrows(result3).join(),
);
updateMessage('proper length returned.');
runTestCase('should merge values', testMerge);
});
});
});
});
});
});
}
function testMerge() {
AsyncStorage.setItem(KEY_MERGE, stringify(VAL_MERGE_1), err1 => {
expectAsyncNoError('testMerge/setItem', err1);
AsyncStorage.mergeItem(KEY_MERGE, stringify(VAL_MERGE_2), err2 => {
expectAsyncNoError('testMerge/mergeItem', err2);
AsyncStorage.getItem(KEY_MERGE, (err3, result) => {
expectAsyncNoError('testMerge/setItem', err3);
expectEqual(
JSON.parse(nullthrows(result)),
VAL_MERGE_EXPECT,
'testMerge',
);
updateMessage('objects deeply merged\nDone!');
runTestCase('multi set and get', testOptimizedMultiGet);
});
});
});
}
function testOptimizedMultiGet() {
let batch = [
[KEY_1, VAL_1],
[KEY_2, VAL_2],
];
let keys = batch.map(([key, value]) => key);
AsyncStorage.multiSet(batch, err1 => {
// yes, twice on purpose
[1, 2].forEach(i => {
expectAsyncNoError(`${i} testOptimizedMultiGet/multiSet`, err1);
AsyncStorage.multiGet(keys, (err2, result) => {
expectAsyncNoError(`${i} testOptimizedMultiGet/multiGet`, err2);
expectEqual(result, batch, `${i} testOptimizedMultiGet multiGet`);
updateMessage(
'multiGet([key_1, key_2]) correctly returned ' + stringify(result),
);
done();
});
});
});
}
class AsyncStorageTest extends React.Component<{...}, $FlowFixMeState> {
state: any | {|done: boolean, messages: string|} = {
messages: 'Initializing...',
done: false,
};
componentDidMount() {
done = () =>
this.setState({done: true}, () => {
TestModule.markTestCompleted();
});
updateMessage = (msg: string) => {
this.setState({messages: this.state.messages.concat('\n' + msg)});
DEBUG && console.log(msg);
};
AsyncStorage.clear(testSetAndGet);
}
render(): React.Node {
return (
<View style={styles.container}>
<Text>
{
/* $FlowFixMe[incompatible-type] (>=0.54.0 site=react_native_fb,react_
* native_oss) This comment suppresses an error found when Flow v0.54
* was deployed. To see the error delete this comment and run Flow.
*/
this.constructor.displayName + ': '
}
{this.state.done ? 'Done' : 'Testing...'}
{'\n\n' + this.state.messages}
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: 'white',
padding: 40,
},
});
AsyncStorageTest.displayName = 'AsyncStorageTest';
module.exports = AsyncStorageTest;
-1
View File
@@ -20,7 +20,6 @@ const {AppRegistry, ScrollView, StyleSheet, Text, TouchableOpacity, View} =
const TESTS = [
require('./IntegrationTestHarnessTest'),
require('./TimersTest'),
require('./AsyncStorageTest'),
require('./LayoutEventsTest'),
require('./AppEventsTest'),
require('./SimpleSnapshotTest'),
-120
View File
@@ -1,120 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
/**
* AsyncStorage is a simple, unencrypted, asynchronous, persistent, key-value storage
* system that is global to the app. It should be used instead of LocalStorage.
*
* It is recommended that you use an abstraction on top of `AsyncStorage`
* instead of `AsyncStorage` directly for anything more than light usage since
* it operates globally.
*
* On iOS, `AsyncStorage` is backed by native code that stores small values in a
* serialized dictionary and larger values in separate files. On Android,
* `AsyncStorage` will use either [RocksDB](http://rocksdb.org/) or SQLite
* based on what is available.
*
* @see https://reactnative.dev/docs/asyncstorage#content
*/
export interface AsyncStorageStatic {
/**
* Fetches key and passes the result to callback, along with an Error if there is any.
*/
getItem(
key: string,
callback?: (error?: Error, result?: string) => void,
): Promise<string | null>;
/**
* Sets value for key and calls callback on completion, along with an Error if there is any
*/
setItem(
key: string,
value: string,
callback?: (error?: Error) => void,
): Promise<void>;
removeItem(key: string, callback?: (error?: Error) => void): Promise<void>;
/**
* Merges existing value with input value, assuming they are stringified json. Returns a Promise object.
* Not supported by all native implementation
*/
mergeItem(
key: string,
value: string,
callback?: (error?: Error) => void,
): Promise<void>;
/**
* Erases all AsyncStorage for all clients, libraries, etc. You probably don't want to call this.
* Use removeItem or multiRemove to clear only your own keys instead.
*/
clear(callback?: (error?: Error) => void): Promise<void>;
/**
* Gets all keys known to the app, for all callers, libraries, etc
*/
getAllKeys(
callback?: (error?: Error, keys?: string[]) => void,
): Promise<string[]>;
/**
* multiGet invokes callback with an array of key-value pair arrays that matches the input format of multiSet
*/
multiGet(
keys: string[],
callback?: (errors?: Error[], result?: [string, string][]) => void,
): Promise<[string, string][]>;
/**
* multiSet and multiMerge take arrays of key-value array pairs that match the output of multiGet,
*
* multiSet([['k1', 'val1'], ['k2', 'val2']], cb);
*/
multiSet(
keyValuePairs: string[][],
callback?: (errors?: Error[]) => void,
): Promise<void>;
/**
* Delete all the keys in the keys array.
*/
multiRemove(
keys: string[],
callback?: (errors?: Error[]) => void,
): Promise<void>;
/**
* Merges existing values with input values, assuming they are stringified json.
* Returns a Promise object.
*
* Not supported by all native implementations.
*/
multiMerge(
keyValuePairs: string[][],
callback?: (errors?: Error[]) => void,
): Promise<void>;
}
/**
* AsyncStorage has been extracted from react-native core and will be removed in a future release.
* It can now be installed and imported from `@react-native-community/async-storage` instead of 'react-native'.
* @see https://github.com/react-native-community/async-storage
* @deprecated
*/
export const AsyncStorage: AsyncStorageStatic;
/**
* AsyncStorage has been extracted from react-native core and will be removed in a future release.
* It can now be installed and imported from `@react-native-community/async-storage` instead of 'react-native'.
* @see https://github.com/react-native-community/async-storage
* @deprecated
*/
export type AsyncStorage = AsyncStorageStatic;
-385
View File
@@ -1,385 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow strict
* @jsdoc
*/
import NativeAsyncLocalStorage from './NativeAsyncLocalStorage';
import NativeAsyncSQLiteDBStorage from './NativeAsyncSQLiteDBStorage';
import invariant from 'invariant';
// Use SQLite if available, otherwise file storage.
const RCTAsyncStorage = NativeAsyncSQLiteDBStorage || NativeAsyncLocalStorage;
type GetRequest = {
keys: Array<string>,
callback: ?(errors: ?Array<Error>, result: ?Array<Array<string>>) => void,
keyIndex: number,
resolve: (
result?:
| void
| null
| Promise<?Array<Array<string>>>
| Array<Array<string>>,
) => void,
reject: (error?: mixed) => void,
};
/**
* `AsyncStorage` is a simple, unencrypted, asynchronous, persistent, key-value
* storage system that is global to the app. It should be used instead of
* LocalStorage.
*
* See https://reactnative.dev/docs/asyncstorage
*/
const AsyncStorage = {
_getRequests: ([]: Array<GetRequest>),
_getKeys: ([]: Array<string>),
_immediate: (null: ?number),
/**
* Fetches an item for a `key` and invokes a callback upon completion.
*
* See https://reactnative.dev/docs/asyncstorage#getitem
*/
getItem: function (
key: string,
callback?: ?(error: ?Error, result: ?string) => void,
): Promise<?string> {
invariant(RCTAsyncStorage, 'RCTAsyncStorage not available');
return new Promise((resolve, reject) => {
RCTAsyncStorage.multiGet([key], function (errors, result) {
// Unpack result to get value from [[key,value]]
const value = result && result[0] && result[0][1] ? result[0][1] : null;
const errs = convertErrors(errors);
callback && callback(errs && errs[0], value);
if (errs) {
reject(errs[0]);
} else {
resolve(value);
}
});
});
},
/**
* Sets the value for a `key` and invokes a callback upon completion.
*
* See https://reactnative.dev/docs/asyncstorage#setitem
*/
setItem: function (
key: string,
value: string,
callback?: ?(error: ?Error) => void,
): Promise<void> {
invariant(RCTAsyncStorage, 'RCTAsyncStorage not available');
return new Promise((resolve, reject) => {
RCTAsyncStorage.multiSet([[key, value]], function (errors) {
const errs = convertErrors(errors);
callback && callback(errs && errs[0]);
if (errs) {
reject(errs[0]);
} else {
resolve();
}
});
});
},
/**
* Removes an item for a `key` and invokes a callback upon completion.
*
* See https://reactnative.dev/docs/asyncstorage#removeitem
*/
removeItem: function (
key: string,
callback?: ?(error: ?Error) => void,
): Promise<void> {
invariant(RCTAsyncStorage, 'RCTAsyncStorage not available');
return new Promise((resolve, reject) => {
RCTAsyncStorage.multiRemove([key], function (errors) {
const errs = convertErrors(errors);
callback && callback(errs && errs[0]);
if (errs) {
reject(errs[0]);
} else {
resolve();
}
});
});
},
/**
* Merges an existing `key` value with an input value, assuming both values
* are stringified JSON.
*
* **NOTE:** This is not supported by all native implementations.
*
* See https://reactnative.dev/docs/asyncstorage#mergeitem
*/
mergeItem: function (
key: string,
value: string,
callback?: ?(error: ?Error) => void,
): Promise<void> {
invariant(RCTAsyncStorage, 'RCTAsyncStorage not available');
return new Promise((resolve, reject) => {
RCTAsyncStorage.multiMerge([[key, value]], function (errors) {
const errs = convertErrors(errors);
callback && callback(errs && errs[0]);
if (errs) {
reject(errs[0]);
} else {
resolve();
}
});
});
},
/**
* Erases *all* `AsyncStorage` for all clients, libraries, etc. You probably
* don't want to call this; use `removeItem` or `multiRemove` to clear only
* your app's keys.
*
* See https://reactnative.dev/docs/asyncstorage#clear
*/
clear: function (callback?: ?(error: ?Error) => void): Promise<void> {
invariant(RCTAsyncStorage, 'RCTAsyncStorage not available');
return new Promise((resolve, reject) => {
RCTAsyncStorage.clear(function (error) {
callback && callback(convertError(error));
if (error && convertError(error)) {
reject(convertError(error));
} else {
resolve();
}
});
});
},
/**
* Gets *all* keys known to your app; for all callers, libraries, etc.
*
* See https://reactnative.dev/docs/asyncstorage#getallkeys
*/
getAllKeys: function (
callback?: ?(error: ?Error, keys: ?Array<string>) => void,
): Promise<?Array<string>> {
invariant(RCTAsyncStorage, 'RCTAsyncStorage not available');
return new Promise((resolve, reject) => {
RCTAsyncStorage.getAllKeys(function (error, keys) {
callback && callback(convertError(error), keys);
if (error) {
reject(convertError(error));
} else {
resolve(keys);
}
});
});
},
/**
* The following batched functions are useful for executing a lot of
* operations at once, allowing for native optimizations and provide the
* convenience of a single callback after all operations are complete.
*
* These functions return arrays of errors, potentially one for every key.
* For key-specific errors, the Error object will have a key property to
* indicate which key caused the error.
*/
/**
* Flushes any pending requests using a single batch call to get the data.
*
* See https://reactnative.dev/docs/asyncstorage#flushgetrequests
* */
/* $FlowFixMe[missing-this-annot] The 'this' type annotation(s) required by
* Flow's LTI update could not be added via codemod */
flushGetRequests: function (): void {
const getRequests = this._getRequests;
const getKeys = this._getKeys;
this._getRequests = [];
this._getKeys = [];
invariant(RCTAsyncStorage, 'RCTAsyncStorage not available');
RCTAsyncStorage.multiGet(getKeys, function (errors, result) {
// Even though the runtime complexity of this is theoretically worse vs if we used a map,
// it's much, much faster in practice for the data sets we deal with (we avoid
// allocating result pair arrays). This was heavily benchmarked.
//
// Is there a way to avoid using the map but fix the bug in this breaking test?
// https://github.com/facebook/react-native/commit/8dd8ad76579d7feef34c014d387bf02065692264
const map: {[string]: string} = {};
result &&
result.forEach(([key, value]) => {
map[key] = value;
return value;
});
const reqLength = getRequests.length;
for (let i = 0; i < reqLength; i++) {
const request = getRequests[i];
const requestKeys = request.keys;
const requestResult = requestKeys.map(key => [key, map[key]]);
request.callback && request.callback(null, requestResult);
request.resolve && request.resolve(requestResult);
}
});
},
/**
* This allows you to batch the fetching of items given an array of `key`
* inputs. Your callback will be invoked with an array of corresponding
* key-value pairs found.
*
* See https://reactnative.dev/docs/asyncstorage#multiget
*/
/* $FlowFixMe[missing-this-annot] The 'this' type annotation(s) required by
* Flow's LTI update could not be added via codemod */
multiGet: function (
keys: Array<string>,
callback?: ?(errors: ?Array<Error>, result: ?Array<Array<string>>) => void,
): Promise<?Array<Array<string>>> {
if (!this._immediate) {
this._immediate = setImmediate(() => {
this._immediate = null;
this.flushGetRequests();
});
}
return new Promise<?Array<Array<string>>>((resolve, reject) => {
this._getRequests.push({
keys,
callback,
// do we need this?
keyIndex: this._getKeys.length,
resolve,
reject,
});
// avoid fetching duplicates
keys.forEach(key => {
if (this._getKeys.indexOf(key) === -1) {
this._getKeys.push(key);
}
});
});
},
/**
* Use this as a batch operation for storing multiple key-value pairs. When
* the operation completes you'll get a single callback with any errors.
*
* See https://reactnative.dev/docs/asyncstorage#multiset
*/
multiSet: function (
keyValuePairs: Array<Array<string>>,
callback?: ?(errors: ?Array<Error>) => void,
): Promise<void> {
invariant(RCTAsyncStorage, 'RCTAsyncStorage not available');
return new Promise((resolve, reject) => {
RCTAsyncStorage.multiSet(keyValuePairs, function (errors) {
const error = convertErrors(errors);
callback && callback(error);
if (error) {
reject(error);
} else {
resolve();
}
});
});
},
/**
* Call this to batch the deletion of all keys in the `keys` array.
*
* See https://reactnative.dev/docs/asyncstorage#multiremove
*/
multiRemove: function (
keys: Array<string>,
callback?: ?(errors: ?Array<Error>) => void,
): Promise<void> {
invariant(RCTAsyncStorage, 'RCTAsyncStorage not available');
return new Promise((resolve, reject) => {
RCTAsyncStorage.multiRemove(keys, function (errors) {
const error = convertErrors(errors);
callback && callback(error);
if (error) {
reject(error);
} else {
resolve();
}
});
});
},
/**
* Batch operation to merge in existing and new values for a given set of
* keys. This assumes that the values are stringified JSON.
*
* **NOTE**: This is not supported by all native implementations.
*
* See https://reactnative.dev/docs/asyncstorage#multimerge
*/
multiMerge: function (
keyValuePairs: Array<Array<string>>,
callback?: ?(errors: ?Array<Error>) => void,
): Promise<void> {
invariant(RCTAsyncStorage, 'RCTAsyncStorage not available');
return new Promise((resolve, reject) => {
RCTAsyncStorage.multiMerge(keyValuePairs, function (errors) {
const error = convertErrors(errors);
callback && callback(error);
if (error) {
reject(error);
} else {
resolve();
}
});
});
},
};
// Not all native implementations support merge.
// TODO: Check whether above comment is correct. multiMerge is guaranteed to
// exist in the module spec so we should be able to just remove this check.
if (RCTAsyncStorage && !RCTAsyncStorage.multiMerge) {
// $FlowFixMe[unclear-type]
delete (AsyncStorage: any).mergeItem;
// $FlowFixMe[unclear-type]
delete (AsyncStorage: any).multiMerge;
}
function convertErrors(
// NOTE: The native module spec only has the Array case, but the Android
// implementation passes a single object.
errs: ?(
| {message: string, key?: string}
| Array<{message: string, key?: string}>
),
) {
if (!errs) {
return null;
}
return (Array.isArray(errs) ? errs : [errs]).map(e => convertError(e));
}
declare function convertError(void | null): null;
declare function convertError({message: string, key?: string}): Error;
/* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's
* LTI update could not be added via codemod */
function convertError(error) {
if (!error) {
return null;
}
const out = new Error(error.message);
// $FlowFixMe[unclear-type]
(out: any).key = error.key;
return out;
}
module.exports = AsyncStorage;
@@ -1,45 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
import type {TurboModule} from '../TurboModule/RCTExport';
import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry';
export interface Spec extends TurboModule {
+getConstants: () => {};
+multiGet: (
keys: Array<string>,
callback: (
errors: ?Array<{message: string, key?: string}>,
kvPairs: ?Array<Array<string>>,
) => void,
) => void;
+multiSet: (
kvPairs: Array<Array<string>>,
callback: (errors: ?Array<{message: string, key?: string}>) => void,
) => void;
+multiMerge: (
kvPairs: Array<Array<string>>,
callback: (errors: ?Array<{message: string, key?: string}>) => void,
) => void;
+multiRemove: (
keys: Array<string>,
callback: (errors: ?Array<{message: string, key?: string}>) => void,
) => void;
+clear: (callback: (error: {message: string, key?: string}) => void) => void;
+getAllKeys: (
callback: (
error: ?{message: string, key?: string},
allKeys: ?Array<string>,
) => void,
) => void;
}
export default (TurboModuleRegistry.get<Spec>('AsyncLocalStorage'): ?Spec);
@@ -1,45 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
import type {TurboModule} from '../TurboModule/RCTExport';
import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry';
export interface Spec extends TurboModule {
+getConstants: () => {};
+multiGet: (
keys: Array<string>,
callback: (
errors: ?Array<{message: string, key?: string}>,
kvPairs: ?Array<Array<string>>,
) => void,
) => void;
+multiSet: (
kvPairs: Array<Array<string>>,
callback: (errors: ?Array<{message: string, key?: string}>) => void,
) => void;
+multiMerge: (
kvPairs: Array<Array<string>>,
callback: (errors: ?Array<{message: string, key?: string}>) => void,
) => void;
+multiRemove: (
keys: Array<string>,
callback: (errors: ?Array<{message: string, key?: string}>) => void,
) => void;
+clear: (callback: (error: {message: string, key?: string}) => void) => void;
+getAllKeys: (
callback: (
error: ?{message: string, key?: string},
allKeys: ?Array<string>,
) => void,
) => void;
}
export default (TurboModuleRegistry.get<Spec>('AsyncSQLiteDBStorage'): ?Spec);
+15 -11
View File
@@ -51,7 +51,6 @@ import typeof * as AnimatedModule from './Libraries/Animated/Animated';
import typeof Appearance from './Libraries/Utilities/Appearance';
import typeof AppRegistry from './Libraries/ReactNative/AppRegistry';
import typeof AppState from './Libraries/AppState/AppState';
import typeof AsyncStorage from './Libraries/Storage/AsyncStorage';
import typeof BackHandler from './Libraries/Utilities/BackHandler';
import typeof Clipboard from './Libraries/Components/Clipboard/Clipboard';
import typeof DeviceInfo from './Libraries/Utilities/DeviceInfo';
@@ -252,16 +251,6 @@ module.exports = {
get AppState(): AppState {
return require('./Libraries/AppState/AppState');
},
// $FlowFixMe[value-as-type]
get AsyncStorage(): AsyncStorage {
warnOnce(
'async-storage-moved',
'AsyncStorage has been extracted from react-native core and will be removed in a future release. ' +
"It can now be installed and imported from '@react-native-async-storage/async-storage' instead of 'react-native'. " +
'See https://github.com/react-native-async-storage/async-storage',
);
return require('./Libraries/Storage/AsyncStorage');
},
get BackHandler(): BackHandler {
return require('./Libraries/Utilities/BackHandler');
},
@@ -761,4 +750,19 @@ if (__DEV__) {
);
},
});
/* $FlowFixMe[prop-missing] This is intentional: Flow will error when
* attempting to access AsyncStorage. */
/* $FlowFixMe[invalid-export] This is intentional: Flow will error when
* attempting to access AsyncStorage. */
Object.defineProperty(module.exports, 'AsyncStorage', {
configurable: true,
get() {
invariant(
false,
'AsyncStorage has been removed from react-native core. ' +
"It can now be installed and imported from '@react-native-async-storage/async-storage' instead of 'react-native'. " +
'See https://github.com/react-native-async-storage/async-storage',
);
},
});
}
-1
View File
@@ -25,7 +25,6 @@ import * as React from 'react';
import {
AccessibilityInfo,
ActionSheetIOS,
AsyncStorage,
Alert,
AppState,
AppStateStatus,
-1
View File
@@ -135,7 +135,6 @@ export * from '../Libraries/Renderer/implementations/ReactNativeRenderer';
export * from '../Libraries/Renderer/shims/ReactNativeTypes';
export * from '../Libraries/Settings/Settings';
export * from '../Libraries/Share/Share';
export * from '../Libraries/Storage/AsyncStorage';
export * from '../Libraries/StyleSheet/PlatformColorValueTypesIOS';
export * from '../Libraries/StyleSheet/PlatformColorValueTypes';
export * from '../Libraries/StyleSheet/StyleSheet';