react-native-mmkv 4.0.0-beta.1 → 4.0.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NitroMmkv.podspec +44 -0
- package/README.md +1 -3
- package/android/CMakeLists.txt +31 -30
- package/android/build.gradle +65 -20
- package/android/fix-prefab.gradle +51 -0
- package/android/gradle.properties +5 -5
- package/android/src/main/cpp/cpp-adapter.cpp +6 -0
- package/android/src/main/java/com/margelo/nitro/mmkv/HybridMMKVPlatformContext.kt +19 -0
- package/android/src/main/java/com/margelo/nitro/mmkv/NitroMmkvPackage.java +33 -0
- package/app.plugin.js +1 -0
- package/cpp/HybridMMKV.cpp +184 -0
- package/cpp/HybridMMKV.hpp +47 -0
- package/cpp/HybridMMKVFactory.cpp +33 -0
- package/cpp/HybridMMKVFactory.hpp +24 -0
- package/cpp/{MmkvTypes.h → MMKVTypes.hpp} +1 -1
- package/cpp/MMKVValueChangedListenerRegistry.cpp +58 -0
- package/cpp/MMKVValueChangedListenerRegistry.hpp +43 -0
- package/cpp/{ManagedMMBuffer.h → ManagedMMBuffer.hpp} +13 -5
- package/ios/HybridMMKVPlatformContext.swift +43 -0
- package/lib/__tests__/hooks.test.d.ts +1 -0
- package/lib/__tests__/hooks.test.js +69 -0
- package/lib/addMemoryWarningListener/addMemoryWarningListener.d.ts +2 -0
- package/lib/addMemoryWarningListener/addMemoryWarningListener.js +25 -0
- package/lib/addMemoryWarningListener/addMemoryWarningListener.mock.d.ts +2 -0
- package/lib/addMemoryWarningListener/addMemoryWarningListener.mock.js +3 -0
- package/lib/addMemoryWarningListener/addMemoryWarningListener.web.d.ts +2 -0
- package/lib/addMemoryWarningListener/addMemoryWarningListener.web.js +3 -0
- package/lib/createMMKV/createMMKV.d.ts +3 -0
- package/lib/createMMKV/createMMKV.js +40 -0
- package/lib/createMMKV/createMMKV.mock.d.ts +5 -0
- package/lib/createMMKV/createMMKV.mock.js +74 -0
- package/lib/createMMKV/createMMKV.web.d.ts +3 -0
- package/lib/createMMKV/createMMKV.web.js +117 -0
- package/lib/createMMKV/createMockMMKV.d.ts +5 -0
- package/lib/createMMKV/createMockMMKV.js +74 -0
- package/lib/createMMKV/getDefaultMMKVInstance.d.ts +2 -0
- package/lib/createMMKV/getDefaultMMKVInstance.js +8 -0
- package/lib/expo-plugin/withMMKV.cjs +26 -0
- package/lib/expo-plugin/withMMKV.d.cts +3 -0
- package/lib/expo-plugin/withMMKV.d.ts +3 -0
- package/lib/expo-plugin/withMMKV.js +17 -0
- package/lib/hooks/createMMKVHook.d.ts +2 -0
- package/lib/hooks/createMMKVHook.js +49 -0
- package/lib/hooks/useMMKV.d.ts +11 -0
- package/lib/hooks/useMMKV.js +23 -0
- package/lib/hooks/useMMKVBoolean.d.ts +11 -0
- package/lib/hooks/useMMKVBoolean.js +12 -0
- package/lib/hooks/useMMKVBuffer.d.ts +11 -0
- package/lib/hooks/useMMKVBuffer.js +12 -0
- package/lib/hooks/useMMKVKeys.d.ts +12 -0
- package/lib/hooks/useMMKVKeys.js +33 -0
- package/lib/hooks/useMMKVListener.d.ts +15 -0
- package/lib/hooks/useMMKVListener.js +26 -0
- package/lib/hooks/useMMKVNumber.d.ts +11 -0
- package/lib/hooks/useMMKVNumber.js +12 -0
- package/lib/hooks/useMMKVObject.d.ts +17 -0
- package/lib/hooks/useMMKVObject.js +38 -0
- package/lib/hooks/useMMKVString.d.ts +11 -0
- package/lib/hooks/useMMKVString.js +12 -0
- package/lib/index.d.ts +11 -0
- package/lib/index.js +11 -0
- package/lib/isTest.d.ts +1 -0
- package/lib/isTest.js +7 -0
- package/lib/specs/MMKV.nitro.d.ts +94 -0
- package/lib/specs/MMKV.nitro.js +1 -0
- package/lib/{typescript/src/NativeMmkv.d.ts → specs/MMKVFactory.nitro.d.ts} +26 -33
- package/lib/specs/MMKVFactory.nitro.js +1 -0
- package/lib/specs/MMKVPlatformContext.nitro.d.ts +18 -0
- package/lib/specs/MMKVPlatformContext.nitro.js +1 -0
- package/lib/{typescript/src → web}/createTextEncoder.d.ts +0 -1
- package/lib/web/createTextEncoder.js +17 -0
- package/nitro.json +28 -0
- package/nitrogen/generated/.gitattributes +1 -0
- package/nitrogen/generated/android/NitroMmkv+autolinking.cmake +80 -0
- package/nitrogen/generated/android/NitroMmkv+autolinking.gradle +27 -0
- package/nitrogen/generated/android/NitroMmkvOnLoad.cpp +54 -0
- package/nitrogen/generated/android/NitroMmkvOnLoad.hpp +25 -0
- package/nitrogen/generated/android/c++/JHybridMMKVPlatformContextSpec.cpp +52 -0
- package/nitrogen/generated/android/c++/JHybridMMKVPlatformContextSpec.hpp +65 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/mmkv/HybridMMKVPlatformContextSpec.kt +56 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/mmkv/NitroMmkvOnLoad.kt +35 -0
- package/nitrogen/generated/ios/NitroMmkv+autolinking.rb +60 -0
- package/nitrogen/generated/ios/NitroMmkv-Swift-Cxx-Bridge.cpp +32 -0
- package/nitrogen/generated/ios/NitroMmkv-Swift-Cxx-Bridge.hpp +77 -0
- package/nitrogen/generated/ios/NitroMmkv-Swift-Cxx-Umbrella.hpp +45 -0
- package/nitrogen/generated/ios/NitroMmkvAutolinking.mm +43 -0
- package/nitrogen/generated/ios/NitroMmkvAutolinking.swift +25 -0
- package/nitrogen/generated/ios/c++/HybridMMKVPlatformContextSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridMMKVPlatformContextSpecSwift.hpp +82 -0
- package/nitrogen/generated/ios/swift/HybridMMKVPlatformContextSpec.swift +50 -0
- package/nitrogen/generated/ios/swift/HybridMMKVPlatformContextSpec_cxx.swift +141 -0
- package/nitrogen/generated/shared/c++/Configuration.hpp +86 -0
- package/nitrogen/generated/shared/c++/HybridMMKVFactorySpec.cpp +23 -0
- package/nitrogen/generated/shared/c++/HybridMMKVFactorySpec.hpp +69 -0
- package/nitrogen/generated/shared/c++/HybridMMKVPlatformContextSpec.cpp +22 -0
- package/nitrogen/generated/shared/c++/HybridMMKVPlatformContextSpec.hpp +64 -0
- package/nitrogen/generated/shared/c++/HybridMMKVSpec.cpp +34 -0
- package/nitrogen/generated/shared/c++/HybridMMKVSpec.hpp +83 -0
- package/nitrogen/generated/shared/c++/Listener.hpp +67 -0
- package/nitrogen/generated/shared/c++/Mode.hpp +76 -0
- package/package.json +74 -122
- package/react-native.config.js +2 -15
- package/src/__tests__/hooks.test.tsx +39 -34
- package/src/addMemoryWarningListener/addMemoryWarningListener.mock.ts +5 -0
- package/src/{MemoryWarningListener.ts → addMemoryWarningListener/addMemoryWarningListener.ts} +12 -12
- package/src/addMemoryWarningListener/addMemoryWarningListener.web.ts +5 -0
- package/src/createMMKV/createMMKV.ts +51 -0
- package/src/{createMMKV.web.ts → createMMKV/createMMKV.web.ts} +58 -46
- package/src/createMMKV/createMockMMKV.ts +78 -0
- package/src/createMMKV/getDefaultMMKVInstance.ts +10 -0
- package/src/expo-plugin/withMMKV.cts +31 -0
- package/src/hooks/createMMKVHook.ts +66 -0
- package/src/hooks/useMMKV.ts +45 -0
- package/src/hooks/useMMKVBoolean.ts +15 -0
- package/src/hooks/useMMKVBuffer.ts +15 -0
- package/src/hooks/useMMKVKeys.ts +36 -0
- package/src/hooks/useMMKVListener.ts +33 -0
- package/src/hooks/useMMKVNumber.ts +15 -0
- package/src/hooks/useMMKVObject.ts +53 -0
- package/src/hooks/useMMKVString.ts +15 -0
- package/src/index.ts +15 -3
- package/src/{PlatformChecker.ts → isTest.ts} +2 -2
- package/src/specs/MMKV.nitro.ts +93 -0
- package/src/specs/MMKVFactory.nitro.ts +87 -0
- package/src/specs/MMKVPlatformContext.nitro.ts +17 -0
- package/src/{createTextEncoder.ts → web/createTextEncoder.ts} +7 -7
- package/android/src/main/cpp/AndroidLogger.cpp +0 -16
- package/android/src/main/java/com/mrousavy/mmkv/MmkvPackage.java +0 -44
- package/android/src/main/java/com/mrousavy/mmkv/MmkvPlatformContextModule.java +0 -26
- package/cpp/MmkvHostObject.cpp +0 -360
- package/cpp/MmkvHostObject.h +0 -31
- package/cpp/MmkvLogger.h +0 -35
- package/cpp/NativeMmkvModule.cpp +0 -43
- package/cpp/NativeMmkvModule.h +0 -31
- package/ios/AppleLogger.mm +0 -16
- package/ios/MmkvOnLoad.mm +0 -25
- package/ios/MmkvPlatformContext.h +0 -19
- package/ios/MmkvPlatformContextModule.mm +0 -55
- package/lib/commonjs/MMKV.js +0 -124
- package/lib/commonjs/MMKV.js.map +0 -1
- package/lib/commonjs/MemoryWarningListener.js +0 -31
- package/lib/commonjs/MemoryWarningListener.js.map +0 -1
- package/lib/commonjs/MemoryWarningListener.web.js +0 -11
- package/lib/commonjs/MemoryWarningListener.web.js.map +0 -1
- package/lib/commonjs/ModuleNotFoundError.js +0 -75
- package/lib/commonjs/ModuleNotFoundError.js.map +0 -1
- package/lib/commonjs/NativeMmkv.js +0 -47
- package/lib/commonjs/NativeMmkv.js.map +0 -1
- package/lib/commonjs/NativeMmkvPlatformContext.js +0 -22
- package/lib/commonjs/NativeMmkvPlatformContext.js.map +0 -1
- package/lib/commonjs/PlatformChecker.js +0 -14
- package/lib/commonjs/PlatformChecker.js.map +0 -1
- package/lib/commonjs/Types.js +0 -26
- package/lib/commonjs/Types.js.map +0 -1
- package/lib/commonjs/createMMKV.js +0 -43
- package/lib/commonjs/createMMKV.js.map +0 -1
- package/lib/commonjs/createMMKV.mock.js +0 -43
- package/lib/commonjs/createMMKV.mock.js.map +0 -1
- package/lib/commonjs/createMMKV.web.js +0 -110
- package/lib/commonjs/createMMKV.web.js.map +0 -1
- package/lib/commonjs/createTextEncoder.js +0 -23
- package/lib/commonjs/createTextEncoder.js.map +0 -1
- package/lib/commonjs/hooks.js +0 -198
- package/lib/commonjs/hooks.js.map +0 -1
- package/lib/commonjs/index.js +0 -40
- package/lib/commonjs/index.js.map +0 -1
- package/lib/commonjs/package.json +0 -1
- package/lib/module/MMKV.js +0 -119
- package/lib/module/MMKV.js.map +0 -1
- package/lib/module/MemoryWarningListener.js +0 -27
- package/lib/module/MemoryWarningListener.js.map +0 -1
- package/lib/module/MemoryWarningListener.web.js +0 -6
- package/lib/module/MemoryWarningListener.web.js.map +0 -1
- package/lib/module/ModuleNotFoundError.js +0 -70
- package/lib/module/ModuleNotFoundError.js.map +0 -1
- package/lib/module/NativeMmkv.js +0 -45
- package/lib/module/NativeMmkv.js.map +0 -1
- package/lib/module/NativeMmkvPlatformContext.js +0 -18
- package/lib/module/NativeMmkvPlatformContext.js.map +0 -1
- package/lib/module/PlatformChecker.js +0 -10
- package/lib/module/PlatformChecker.js.map +0 -1
- package/lib/module/Types.js +0 -25
- package/lib/module/Types.js.map +0 -1
- package/lib/module/createMMKV.js +0 -38
- package/lib/module/createMMKV.js.map +0 -1
- package/lib/module/createMMKV.mock.js +0 -38
- package/lib/module/createMMKV.mock.js.map +0 -1
- package/lib/module/createMMKV.web.js +0 -105
- package/lib/module/createMMKV.web.js.map +0 -1
- package/lib/module/createTextEncoder.js +0 -19
- package/lib/module/createTextEncoder.js.map +0 -1
- package/lib/module/hooks.js +0 -189
- package/lib/module/hooks.js.map +0 -1
- package/lib/module/index.js +0 -6
- package/lib/module/index.js.map +0 -1
- package/lib/module/package.json +0 -1
- package/lib/typescript/src/MMKV.d.ts +0 -34
- package/lib/typescript/src/MMKV.d.ts.map +0 -1
- package/lib/typescript/src/MemoryWarningListener.d.ts +0 -3
- package/lib/typescript/src/MemoryWarningListener.d.ts.map +0 -1
- package/lib/typescript/src/MemoryWarningListener.web.d.ts +0 -3
- package/lib/typescript/src/MemoryWarningListener.web.d.ts.map +0 -1
- package/lib/typescript/src/ModuleNotFoundError.d.ts +0 -7
- package/lib/typescript/src/ModuleNotFoundError.d.ts.map +0 -1
- package/lib/typescript/src/NativeMmkv.d.ts.map +0 -1
- package/lib/typescript/src/NativeMmkvPlatformContext.d.ts +0 -20
- package/lib/typescript/src/NativeMmkvPlatformContext.d.ts.map +0 -1
- package/lib/typescript/src/PlatformChecker.d.ts +0 -2
- package/lib/typescript/src/PlatformChecker.d.ts.map +0 -1
- package/lib/typescript/src/Types.d.ts +0 -172
- package/lib/typescript/src/Types.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/hooks.test.d.ts +0 -2
- package/lib/typescript/src/__tests__/hooks.test.d.ts.map +0 -1
- package/lib/typescript/src/createMMKV.d.ts +0 -3
- package/lib/typescript/src/createMMKV.d.ts.map +0 -1
- package/lib/typescript/src/createMMKV.mock.d.ts +0 -3
- package/lib/typescript/src/createMMKV.mock.d.ts.map +0 -1
- package/lib/typescript/src/createMMKV.web.d.ts +0 -3
- package/lib/typescript/src/createMMKV.web.d.ts.map +0 -1
- package/lib/typescript/src/createTextEncoder.d.ts.map +0 -1
- package/lib/typescript/src/hooks.d.ts +0 -86
- package/lib/typescript/src/hooks.d.ts.map +0 -1
- package/lib/typescript/src/index.d.ts +0 -4
- package/lib/typescript/src/index.d.ts.map +0 -1
- package/react-native-mmkv.podspec +0 -32
- package/src/MMKV.ts +0 -142
- package/src/MemoryWarningListener.web.ts +0 -5
- package/src/ModuleNotFoundError.ts +0 -95
- package/src/NativeMmkv.ts +0 -118
- package/src/NativeMmkvPlatformContext.ts +0 -38
- package/src/Types.ts +0 -178
- package/src/createMMKV.mock.ts +0 -38
- package/src/createMMKV.ts +0 -42
- package/src/hooks.ts +0 -247
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { NitroModules } from 'react-native-nitro-modules'
|
|
2
|
+
import type { MMKV } from '../specs/MMKV.nitro'
|
|
3
|
+
import type { Configuration, MMKVFactory } from '../specs/MMKVFactory.nitro'
|
|
4
|
+
import type { MMKVPlatformContext } from '../specs/MMKVPlatformContext.nitro'
|
|
5
|
+
import { Platform } from 'react-native'
|
|
6
|
+
import { addMemoryWarningListener } from '../addMemoryWarningListener/addMemoryWarningListener'
|
|
7
|
+
import { isTest } from '../isTest'
|
|
8
|
+
import { createMockMMKV } from './createMockMMKV'
|
|
9
|
+
|
|
10
|
+
let factory: MMKVFactory | undefined
|
|
11
|
+
let platformContext: MMKVPlatformContext | undefined
|
|
12
|
+
|
|
13
|
+
export function createMMKV(configuration?: Configuration): MMKV {
|
|
14
|
+
if (isTest()) {
|
|
15
|
+
// In a test environment, we mock the MMKV instance.
|
|
16
|
+
return createMockMMKV()
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (platformContext == null) {
|
|
20
|
+
// Lazy-init the platform-context HybridObject
|
|
21
|
+
platformContext = NitroModules.createHybridObject<MMKVPlatformContext>(
|
|
22
|
+
'MMKVPlatformContext'
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
if (factory == null) {
|
|
26
|
+
// Lazy-init the factory HybridObject
|
|
27
|
+
factory = NitroModules.createHybridObject<MMKVFactory>('MMKVFactory')
|
|
28
|
+
const baseDirectory = platformContext.getBaseDirectory()
|
|
29
|
+
factory.initializeMMKV(baseDirectory)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Pre-parse the config
|
|
33
|
+
let config = configuration ?? { id: factory.defaultMMKVInstanceId }
|
|
34
|
+
|
|
35
|
+
if (Platform.OS === 'ios') {
|
|
36
|
+
if (config.path == null) {
|
|
37
|
+
// If the user set an App Group directory in Info.plist, let's use
|
|
38
|
+
// the App Group as a MMKV path:
|
|
39
|
+
const appGroupDirectory = platformContext.getAppGroupDirectory()
|
|
40
|
+
if (appGroupDirectory != null) {
|
|
41
|
+
config.path = appGroupDirectory
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Creates the C++ MMKV HybridObject
|
|
47
|
+
const mmkv = factory.createMMKV(config)
|
|
48
|
+
// Add a hook that trims the storage when we get a memory warning
|
|
49
|
+
addMemoryWarningListener(mmkv)
|
|
50
|
+
return mmkv
|
|
51
|
+
}
|
|
@@ -1,44 +1,46 @@
|
|
|
1
|
-
|
|
2
|
-
import type { Configuration
|
|
3
|
-
import { createTextEncoder } from '
|
|
1
|
+
import type { MMKV } from '../specs/MMKV.nitro'
|
|
2
|
+
import type { Configuration } from '../specs/MMKVFactory.nitro'
|
|
3
|
+
import { createTextEncoder } from '../web/createTextEncoder'
|
|
4
4
|
|
|
5
5
|
const canUseDOM =
|
|
6
|
-
typeof window !== 'undefined' && window.document?.createElement != null
|
|
6
|
+
typeof window !== 'undefined' && window.document?.createElement != null
|
|
7
7
|
|
|
8
8
|
const hasAccessToLocalStorage = () => {
|
|
9
9
|
try {
|
|
10
10
|
// throws ACCESS_DENIED error
|
|
11
|
-
window.localStorage
|
|
11
|
+
window.localStorage
|
|
12
12
|
|
|
13
|
-
return true
|
|
13
|
+
return true
|
|
14
14
|
} catch {
|
|
15
|
-
return false
|
|
15
|
+
return false
|
|
16
16
|
}
|
|
17
|
-
}
|
|
17
|
+
}
|
|
18
18
|
|
|
19
|
-
const KEY_WILDCARD = '\\'
|
|
20
|
-
const inMemoryStorage = new Map<string, string>()
|
|
19
|
+
const KEY_WILDCARD = '\\'
|
|
20
|
+
const inMemoryStorage = new Map<string, string>()
|
|
21
21
|
|
|
22
|
-
export
|
|
22
|
+
export function createMMKV(
|
|
23
|
+
config: Configuration = { id: 'mmkv.default' }
|
|
24
|
+
): MMKV {
|
|
23
25
|
if (config.encryptionKey != null) {
|
|
24
|
-
throw new Error("MMKV: 'encryptionKey' is not supported on Web!")
|
|
26
|
+
throw new Error("MMKV: 'encryptionKey' is not supported on Web!")
|
|
25
27
|
}
|
|
26
28
|
if (config.path != null) {
|
|
27
|
-
throw new Error("MMKV: 'path' is not supported on Web!")
|
|
29
|
+
throw new Error("MMKV: 'path' is not supported on Web!")
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
// canUseDOM check prevents spam in Node server environments, such as Next.js server side props.
|
|
31
33
|
if (!hasAccessToLocalStorage() && canUseDOM) {
|
|
32
34
|
console.warn(
|
|
33
35
|
'MMKV: LocalStorage has been disabled. Your experience will be limited to in-memory storage!'
|
|
34
|
-
)
|
|
36
|
+
)
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
const storage = () => {
|
|
38
40
|
if (!canUseDOM) {
|
|
39
41
|
throw new Error(
|
|
40
42
|
'Tried to access storage on the server. Did you forget to call this in useEffect?'
|
|
41
|
-
)
|
|
43
|
+
)
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
if (!hasAccessToLocalStorage()) {
|
|
@@ -50,78 +52,88 @@ export const createMMKV = (config: Configuration): NativeMMKV => {
|
|
|
50
52
|
clear: () => inMemoryStorage.clear(),
|
|
51
53
|
length: inMemoryStorage.size,
|
|
52
54
|
key: (index: number) => Object.keys(inMemoryStorage).at(index) ?? null,
|
|
53
|
-
} as Storage
|
|
55
|
+
} as Storage
|
|
54
56
|
}
|
|
55
57
|
|
|
56
58
|
const domStorage =
|
|
57
|
-
global?.localStorage ?? window?.localStorage ?? localStorage
|
|
59
|
+
global?.localStorage ?? window?.localStorage ?? localStorage
|
|
58
60
|
if (domStorage == null) {
|
|
59
|
-
throw new Error(`Could not find 'localStorage' instance!`)
|
|
61
|
+
throw new Error(`Could not find 'localStorage' instance!`)
|
|
60
62
|
}
|
|
61
|
-
return domStorage
|
|
62
|
-
}
|
|
63
|
+
return domStorage
|
|
64
|
+
}
|
|
63
65
|
|
|
64
|
-
const textEncoder = createTextEncoder()
|
|
66
|
+
const textEncoder = createTextEncoder()
|
|
67
|
+
const listeners = new Set<(key: string) => void>()
|
|
65
68
|
|
|
66
69
|
if (config.id.includes(KEY_WILDCARD)) {
|
|
67
|
-
throw new Error(
|
|
68
|
-
'MMKV: `id` cannot contain the backslash character (`\\`)!'
|
|
69
|
-
);
|
|
70
|
+
throw new Error('MMKV: `id` cannot contain the backslash character (`\\`)!')
|
|
70
71
|
}
|
|
71
72
|
|
|
72
|
-
const keyPrefix = `${config.id}${KEY_WILDCARD}
|
|
73
|
+
const keyPrefix = `${config.id}${KEY_WILDCARD}` // mmkv.default\\
|
|
73
74
|
const prefixedKey = (key: string) => {
|
|
74
75
|
if (key.includes('\\')) {
|
|
75
76
|
throw new Error(
|
|
76
77
|
'MMKV: `key` cannot contain the backslash character (`\\`)!'
|
|
77
|
-
)
|
|
78
|
+
)
|
|
78
79
|
}
|
|
79
|
-
return `${keyPrefix}${key}
|
|
80
|
-
}
|
|
80
|
+
return `${keyPrefix}${key}`
|
|
81
|
+
}
|
|
81
82
|
|
|
82
83
|
return {
|
|
83
84
|
clearAll: () => {
|
|
84
|
-
const keys = Object.keys(storage())
|
|
85
|
+
const keys = Object.keys(storage())
|
|
85
86
|
for (const key of keys) {
|
|
86
87
|
if (key.startsWith(keyPrefix)) {
|
|
87
|
-
storage().removeItem(key)
|
|
88
|
+
storage().removeItem(key)
|
|
88
89
|
}
|
|
89
90
|
}
|
|
90
91
|
},
|
|
91
|
-
|
|
92
|
+
remove: (key) => storage().removeItem(prefixedKey(key)) ?? false,
|
|
92
93
|
set: (key, value) => {
|
|
93
|
-
storage().setItem(prefixedKey(key), value.toString())
|
|
94
|
+
storage().setItem(prefixedKey(key), value.toString())
|
|
94
95
|
},
|
|
95
96
|
getString: (key) => storage().getItem(prefixedKey(key)) ?? undefined,
|
|
96
97
|
getNumber: (key) => {
|
|
97
|
-
const value = storage().getItem(prefixedKey(key))
|
|
98
|
-
if (value == null) return undefined
|
|
99
|
-
return Number(value)
|
|
98
|
+
const value = storage().getItem(prefixedKey(key))
|
|
99
|
+
if (value == null) return undefined
|
|
100
|
+
return Number(value)
|
|
100
101
|
},
|
|
101
102
|
getBoolean: (key) => {
|
|
102
|
-
const value = storage().getItem(prefixedKey(key))
|
|
103
|
-
if (value == null) return undefined
|
|
104
|
-
return value === 'true'
|
|
103
|
+
const value = storage().getItem(prefixedKey(key))
|
|
104
|
+
if (value == null) return undefined
|
|
105
|
+
return value === 'true'
|
|
105
106
|
},
|
|
106
107
|
getBuffer: (key) => {
|
|
107
|
-
const value = storage().getItem(prefixedKey(key))
|
|
108
|
-
if (value == null) return undefined
|
|
109
|
-
return textEncoder.encode(value).buffer
|
|
108
|
+
const value = storage().getItem(prefixedKey(key))
|
|
109
|
+
if (value == null) return undefined
|
|
110
|
+
return textEncoder.encode(value).buffer
|
|
110
111
|
},
|
|
111
112
|
getAllKeys: () => {
|
|
112
|
-
const keys = Object.keys(storage())
|
|
113
|
+
const keys = Object.keys(storage())
|
|
113
114
|
return keys
|
|
114
115
|
.filter((key) => key.startsWith(keyPrefix))
|
|
115
|
-
.map((key) => key.slice(keyPrefix.length))
|
|
116
|
+
.map((key) => key.slice(keyPrefix.length))
|
|
116
117
|
},
|
|
117
118
|
contains: (key) => storage().getItem(prefixedKey(key)) != null,
|
|
118
119
|
recrypt: () => {
|
|
119
|
-
throw new Error('`recrypt(..)` is not supported on Web!')
|
|
120
|
+
throw new Error('`recrypt(..)` is not supported on Web!')
|
|
120
121
|
},
|
|
121
122
|
size: 0,
|
|
122
123
|
isReadOnly: false,
|
|
123
124
|
trim: () => {
|
|
124
125
|
// no-op
|
|
125
126
|
},
|
|
126
|
-
|
|
127
|
-
|
|
127
|
+
dispose: () => {},
|
|
128
|
+
equals: () => false,
|
|
129
|
+
name: 'MMKV',
|
|
130
|
+
addOnValueChangedListener: (listener) => {
|
|
131
|
+
listeners.add(listener)
|
|
132
|
+
return {
|
|
133
|
+
remove: () => {
|
|
134
|
+
listeners.delete(listener)
|
|
135
|
+
},
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { MMKV } from '../specs/MMKV.nitro'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Mock MMKV instance when used in a Jest/Test environment.
|
|
5
|
+
*/
|
|
6
|
+
export function createMockMMKV(): MMKV {
|
|
7
|
+
const storage = new Map<string, string | boolean | number | ArrayBuffer>()
|
|
8
|
+
const listeners = new Set<(key: string) => void>()
|
|
9
|
+
|
|
10
|
+
const notifyListeners = (key: string) => {
|
|
11
|
+
listeners.forEach((listener) => {
|
|
12
|
+
listener(key)
|
|
13
|
+
})
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
clearAll: () => {
|
|
18
|
+
const keysBefore = storage.keys()
|
|
19
|
+
storage.clear()
|
|
20
|
+
// Notify all listeners for all keys that were cleared
|
|
21
|
+
for (const key of keysBefore) {
|
|
22
|
+
notifyListeners(key)
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
remove: (key) => {
|
|
26
|
+
const deleted = storage.delete(key)
|
|
27
|
+
if (deleted) {
|
|
28
|
+
notifyListeners(key)
|
|
29
|
+
}
|
|
30
|
+
return deleted
|
|
31
|
+
},
|
|
32
|
+
set: (key, value) => {
|
|
33
|
+
storage.set(key, value)
|
|
34
|
+
notifyListeners(key)
|
|
35
|
+
},
|
|
36
|
+
getString: (key) => {
|
|
37
|
+
const result = storage.get(key)
|
|
38
|
+
return typeof result === 'string' ? result : undefined
|
|
39
|
+
},
|
|
40
|
+
getNumber: (key) => {
|
|
41
|
+
const result = storage.get(key)
|
|
42
|
+
return typeof result === 'number' ? result : undefined
|
|
43
|
+
},
|
|
44
|
+
getBoolean: (key) => {
|
|
45
|
+
const result = storage.get(key)
|
|
46
|
+
return typeof result === 'boolean' ? result : undefined
|
|
47
|
+
},
|
|
48
|
+
getBuffer: (key) => {
|
|
49
|
+
const result = storage.get(key)
|
|
50
|
+
return result instanceof ArrayBuffer ? result : undefined
|
|
51
|
+
},
|
|
52
|
+
getAllKeys: () => Array.from(storage.keys()),
|
|
53
|
+
contains: (key) => storage.has(key),
|
|
54
|
+
recrypt: () => {
|
|
55
|
+
console.warn('Encryption is not supported in mocked MMKV instances!')
|
|
56
|
+
},
|
|
57
|
+
get size(): number {
|
|
58
|
+
return storage.size
|
|
59
|
+
},
|
|
60
|
+
isReadOnly: false,
|
|
61
|
+
trim: () => {
|
|
62
|
+
// no-op
|
|
63
|
+
},
|
|
64
|
+
name: 'MMKV',
|
|
65
|
+
dispose: () => {},
|
|
66
|
+
equals: () => {
|
|
67
|
+
return false
|
|
68
|
+
},
|
|
69
|
+
addOnValueChangedListener: (listener) => {
|
|
70
|
+
listeners.add(listener)
|
|
71
|
+
return {
|
|
72
|
+
remove: () => {
|
|
73
|
+
listeners.delete(listener)
|
|
74
|
+
},
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { MMKV } from '../specs/MMKV.nitro'
|
|
2
|
+
import { createMMKV } from './createMMKV'
|
|
3
|
+
|
|
4
|
+
let defaultInstance: MMKV | null = null
|
|
5
|
+
export function getDefaultMMKVInstance(): MMKV {
|
|
6
|
+
if (defaultInstance == null) {
|
|
7
|
+
defaultInstance = createMMKV()
|
|
8
|
+
}
|
|
9
|
+
return defaultInstance
|
|
10
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { ConfigPlugin, ExportedConfigWithProps } from '@expo/config-plugins'
|
|
2
|
+
const { createRunOncePlugin, withGradleProperties } = require('@expo/config-plugins')
|
|
3
|
+
import type { Properties } from '@expo/config-plugins/build/android'
|
|
4
|
+
|
|
5
|
+
const pkg = require('../../package.json')
|
|
6
|
+
|
|
7
|
+
const withMMKV: ConfigPlugin<{}> = (config) => {
|
|
8
|
+
// remove 32-bit architectures from gradle.properties
|
|
9
|
+
return withGradleProperties(config, (cfg: ExportedConfigWithProps<Properties.PropertiesItem[]>) => {
|
|
10
|
+
// Define the wanted property
|
|
11
|
+
const property = {
|
|
12
|
+
type: 'property',
|
|
13
|
+
key: 'reactNativeArchitectures',
|
|
14
|
+
value: 'arm64-v8a,x86_64',
|
|
15
|
+
} as const
|
|
16
|
+
// If it exists, update its value
|
|
17
|
+
const index = cfg.modResults.findIndex(
|
|
18
|
+
(p) => p.type === 'property' && p.key === property.key
|
|
19
|
+
)
|
|
20
|
+
if (index !== -1) {
|
|
21
|
+
// Overwrite it
|
|
22
|
+
cfg.modResults[index] = property
|
|
23
|
+
} else {
|
|
24
|
+
// Append it
|
|
25
|
+
cfg.modResults.push(property)
|
|
26
|
+
}
|
|
27
|
+
return cfg
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export = createRunOncePlugin(withMMKV, pkg.name, pkg.version) as ConfigPlugin<{}>
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { useCallback, useEffect, useMemo, useState } from 'react'
|
|
2
|
+
import { getDefaultMMKVInstance } from '../createMMKV/getDefaultMMKVInstance'
|
|
3
|
+
import type { MMKV } from '../specs/MMKV.nitro'
|
|
4
|
+
|
|
5
|
+
export function createMMKVHook<
|
|
6
|
+
T extends (boolean | number | string | ArrayBufferLike) | undefined,
|
|
7
|
+
TSet extends T | undefined,
|
|
8
|
+
TSetAction extends TSet | ((current: T) => TSet),
|
|
9
|
+
>(getter: (instance: MMKV, key: string) => T) {
|
|
10
|
+
return (
|
|
11
|
+
key: string,
|
|
12
|
+
instance?: MMKV
|
|
13
|
+
): [value: T, setValue: (value: TSetAction) => void] => {
|
|
14
|
+
const mmkv = instance ?? getDefaultMMKVInstance()
|
|
15
|
+
|
|
16
|
+
const [bump, setBump] = useState(0)
|
|
17
|
+
const value = useMemo(() => {
|
|
18
|
+
// bump is here as an additional outside dependency, so this useMemo
|
|
19
|
+
// re-computes the value each time bump changes, effectively acting as a hint
|
|
20
|
+
// that the outside value (storage) has changed. setting bump refreshes this value.
|
|
21
|
+
bump
|
|
22
|
+
return getter(mmkv, key)
|
|
23
|
+
}, [mmkv, key, bump])
|
|
24
|
+
|
|
25
|
+
// update value by user set
|
|
26
|
+
const set = useCallback(
|
|
27
|
+
(v: TSetAction) => {
|
|
28
|
+
const newValue = typeof v === 'function' ? v(getter(mmkv, key)) : v
|
|
29
|
+
switch (typeof newValue) {
|
|
30
|
+
case 'number':
|
|
31
|
+
case 'string':
|
|
32
|
+
case 'boolean':
|
|
33
|
+
mmkv.set(key, newValue)
|
|
34
|
+
break
|
|
35
|
+
case 'undefined':
|
|
36
|
+
mmkv.remove(key)
|
|
37
|
+
break
|
|
38
|
+
case 'object':
|
|
39
|
+
if (newValue instanceof ArrayBuffer) {
|
|
40
|
+
mmkv.set(key, newValue)
|
|
41
|
+
break
|
|
42
|
+
} else {
|
|
43
|
+
throw new Error(
|
|
44
|
+
`MMKV: Type object (${newValue}) is not supported!`
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
default:
|
|
48
|
+
throw new Error(`MMKV: Type ${typeof newValue} is not supported!`)
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
[key, mmkv]
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
// update value if it changes somewhere else (second hook, same key)
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
const listener = mmkv.addOnValueChangedListener((changedKey) => {
|
|
57
|
+
if (changedKey === key) {
|
|
58
|
+
setBump((b) => b + 1)
|
|
59
|
+
}
|
|
60
|
+
})
|
|
61
|
+
return () => listener.remove()
|
|
62
|
+
}, [key, mmkv])
|
|
63
|
+
|
|
64
|
+
return [value, set]
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { useRef } from 'react'
|
|
2
|
+
import type { MMKV } from '../specs/MMKV.nitro'
|
|
3
|
+
import type { Configuration } from '../specs/MMKVFactory.nitro'
|
|
4
|
+
import { getDefaultMMKVInstance } from '../createMMKV/getDefaultMMKVInstance'
|
|
5
|
+
import { createMMKV } from '../createMMKV/createMMKV'
|
|
6
|
+
|
|
7
|
+
function isConfigurationEqual(
|
|
8
|
+
left?: Configuration,
|
|
9
|
+
right?: Configuration
|
|
10
|
+
): boolean {
|
|
11
|
+
if (left == null || right == null) return left == null && right == null
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
left.encryptionKey === right.encryptionKey &&
|
|
15
|
+
left.id === right.id &&
|
|
16
|
+
left.path === right.path &&
|
|
17
|
+
left.mode === right.mode
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Use the default, shared MMKV instance.
|
|
23
|
+
*/
|
|
24
|
+
export function useMMKV(): MMKV
|
|
25
|
+
/**
|
|
26
|
+
* Use a custom MMKV instance with the given configuration.
|
|
27
|
+
* @param configuration The configuration to initialize the MMKV instance with. Does not have to be memoized.
|
|
28
|
+
*/
|
|
29
|
+
export function useMMKV(configuration: Configuration): MMKV
|
|
30
|
+
export function useMMKV(configuration?: Configuration): MMKV {
|
|
31
|
+
const instance = useRef<MMKV>(undefined)
|
|
32
|
+
const lastConfiguration = useRef<Configuration>(undefined)
|
|
33
|
+
|
|
34
|
+
if (configuration == null) return getDefaultMMKVInstance()
|
|
35
|
+
|
|
36
|
+
if (
|
|
37
|
+
instance.current == null ||
|
|
38
|
+
!isConfigurationEqual(lastConfiguration.current, configuration)
|
|
39
|
+
) {
|
|
40
|
+
lastConfiguration.current = configuration
|
|
41
|
+
instance.current = createMMKV(configuration)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return instance.current
|
|
45
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createMMKVHook } from './createMMKVHook'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Use the boolean value of the given `key` from the given MMKV storage instance.
|
|
5
|
+
*
|
|
6
|
+
* If no instance is provided, a shared default instance will be used.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const [isPremiumAccount, setIsPremiumAccount] = useMMKVBoolean("user.isPremium")
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export const useMMKVBoolean = createMMKVHook((instance, key) =>
|
|
14
|
+
instance.getBoolean(key)
|
|
15
|
+
)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createMMKVHook } from './createMMKVHook'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Use the buffer value (unsigned 8-bit (0-255)) of the given `key` from the given MMKV storage instance.
|
|
5
|
+
*
|
|
6
|
+
* If no instance is provided, a shared default instance will be used.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const [privateKey, setPrivateKey] = useMMKVBuffer("user.privateKey")
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export const useMMKVBuffer = createMMKVHook((instance, key) =>
|
|
14
|
+
instance.getBuffer(key)
|
|
15
|
+
)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { useState } from 'react'
|
|
2
|
+
import type { MMKV } from '../specs/MMKV.nitro'
|
|
3
|
+
import { getDefaultMMKVInstance } from '../createMMKV/getDefaultMMKVInstance'
|
|
4
|
+
import { useMMKVListener } from './useMMKVListener'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Get a list of all keys that exist in the given MMKV {@linkcode instance}.
|
|
8
|
+
* The keys update when new keys are added or removed.
|
|
9
|
+
* @param instance The instance to listen to changes to (or the default instance)
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* useMMKVKeys(instance)
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export function useMMKVKeys(instance?: MMKV): string[] {
|
|
17
|
+
const mmkv = instance ?? getDefaultMMKVInstance()
|
|
18
|
+
const [allKeys, setKeys] = useState<string[]>(() => mmkv.getAllKeys())
|
|
19
|
+
|
|
20
|
+
useMMKVListener((key) => {
|
|
21
|
+
// a key changed
|
|
22
|
+
setKeys((keys) => {
|
|
23
|
+
const currentlyHasKey = keys.includes(key)
|
|
24
|
+
const hasKey = mmkv.contains(key)
|
|
25
|
+
if (hasKey !== currentlyHasKey) {
|
|
26
|
+
// Re-fetch the keys from native
|
|
27
|
+
return mmkv.getAllKeys()
|
|
28
|
+
} else {
|
|
29
|
+
// We are up-to-date.
|
|
30
|
+
return keys
|
|
31
|
+
}
|
|
32
|
+
})
|
|
33
|
+
}, mmkv)
|
|
34
|
+
|
|
35
|
+
return allKeys
|
|
36
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react'
|
|
2
|
+
import type { MMKV } from '../specs/MMKV.nitro'
|
|
3
|
+
import { getDefaultMMKVInstance } from '../createMMKV/getDefaultMMKVInstance'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Listen for changes in the given MMKV storage instance.
|
|
7
|
+
* If no instance is passed, the default instance will be used.
|
|
8
|
+
* @param valueChangedListener The function to call whenever a value inside the storage instance changes
|
|
9
|
+
* @param instance The instance to listen to changes to (or the default instance)
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* useMMKVListener((key) => {
|
|
14
|
+
* console.log(`Value for "${key}" changed!`)
|
|
15
|
+
* })
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export function useMMKVListener(
|
|
19
|
+
valueChangedListener: (key: string) => void,
|
|
20
|
+
instance?: MMKV
|
|
21
|
+
): void {
|
|
22
|
+
const ref = useRef(valueChangedListener)
|
|
23
|
+
ref.current = valueChangedListener
|
|
24
|
+
|
|
25
|
+
const mmkv = instance ?? getDefaultMMKVInstance()
|
|
26
|
+
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
const listener = mmkv.addOnValueChangedListener((changedKey) => {
|
|
29
|
+
ref.current(changedKey)
|
|
30
|
+
})
|
|
31
|
+
return () => listener.remove()
|
|
32
|
+
}, [mmkv])
|
|
33
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createMMKVHook } from './createMMKVHook'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Use the number value of the given `key` from the given MMKV storage instance.
|
|
5
|
+
*
|
|
6
|
+
* If no instance is provided, a shared default instance will be used.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const [age, setAge] = useMMKVNumber("user.age")
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export const useMMKVNumber = createMMKVHook((instance, key) =>
|
|
14
|
+
instance.getNumber(key)
|
|
15
|
+
)
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { useCallback, useMemo } from 'react'
|
|
2
|
+
import type { MMKV } from '../specs/MMKV.nitro'
|
|
3
|
+
import { useMMKVString } from './useMMKVString'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Use an object value of the given `key` from the given MMKV storage instance.
|
|
7
|
+
*
|
|
8
|
+
* If no instance is provided, a shared default instance will be used.
|
|
9
|
+
*
|
|
10
|
+
* The object will be serialized using `JSON`.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* const [user, setUser] = useMMKVObject<User>("user")
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export function useMMKVObject<T>(
|
|
18
|
+
key: string,
|
|
19
|
+
instance?: MMKV
|
|
20
|
+
): [
|
|
21
|
+
value: T | undefined,
|
|
22
|
+
setValue: (
|
|
23
|
+
value: T | undefined | ((prevValue: T | undefined) => T | undefined)
|
|
24
|
+
) => void,
|
|
25
|
+
] {
|
|
26
|
+
const [json, setJson] = useMMKVString(key, instance)
|
|
27
|
+
|
|
28
|
+
const value = useMemo(() => {
|
|
29
|
+
if (json == null) return undefined
|
|
30
|
+
return JSON.parse(json) as T
|
|
31
|
+
}, [json])
|
|
32
|
+
|
|
33
|
+
const setValue = useCallback(
|
|
34
|
+
(v: (T | undefined) | ((prev: T | undefined) => T | undefined)) => {
|
|
35
|
+
if (v instanceof Function) {
|
|
36
|
+
setJson((currentJson) => {
|
|
37
|
+
const currentValue =
|
|
38
|
+
currentJson != null ? (JSON.parse(currentJson) as T) : undefined
|
|
39
|
+
const newValue = v(currentValue)
|
|
40
|
+
// Store the Object as a serialized Value or clear the value
|
|
41
|
+
return newValue != null ? JSON.stringify(newValue) : undefined
|
|
42
|
+
})
|
|
43
|
+
} else {
|
|
44
|
+
// Store the Object as a serialized Value or clear the value
|
|
45
|
+
const newValue = v != null ? JSON.stringify(v) : undefined
|
|
46
|
+
setJson(newValue)
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
[setJson]
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
return [value, setValue]
|
|
53
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createMMKVHook } from './createMMKVHook'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Use the string value of the given `key` from the given MMKV storage instance.
|
|
5
|
+
*
|
|
6
|
+
* If no instance is provided, a shared default instance will be used.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const [username, setUsername] = useMMKVString("user.name")
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export const useMMKVString = createMMKVHook((instance, key) =>
|
|
14
|
+
instance.getString(key)
|
|
15
|
+
)
|