Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/mrousavy/react-native-mmkv

⚡️ The fastest key/value storage for React Native. ~30x faster than AsyncStorage!
https://github.com/mrousavy/react-native-mmkv

android cpp database fast hacktoberfest ios jni jsi localstorage mmkv native-module react react-native storage turbomodule

Last synced: 5 days ago
JSON representation

⚡️ The fastest key/value storage for React Native. ~30x faster than AsyncStorage!

Awesome Lists containing this project

README

        





react-native-mmkv


MMKV


The fastest key/value storage for React Native.














This library helped you? Consider sponsoring!



* **MMKV** is an efficient, small mobile key-value storage framework developed by WeChat. See [Tencent/MMKV](https://github.com/Tencent/MMKV) for more information
* **react-native-mmkv** is a library that allows you to easily use **MMKV** inside your React Native app through fast and direct JS bindings to the native C++ library.

## Features

* **Get** and **set** strings, booleans, numbers and ArrayBuffers
* **Fully synchronous** calls, no async/await, no Promises, no Bridge.
* **Encryption** support (secure storage)
* **Multiple instances** support (separate user-data with global data)
* **Customizable storage location**
* **High performance** because everything is **written in C++**
* **~30x faster than AsyncStorage**
* Uses [**JSI**](https://reactnative.dev/docs/the-new-architecture/landing-page#fast-javascriptnative-interfacing) and [**C++ TurboModules**](https://github.com/reactwg/react-native-new-architecture/blob/main/docs/turbo-modules-xplat.md) instead of the "old" Bridge
* **iOS**, **Android** and **Web** support
* Easy to use **React Hooks** API

## react-native-mmkv V3

> [!IMPORTANT]
> react-native-mmkv V3 is now a pure C++ TurboModule, and **requires the new architecture to be enabled**. (react-native 0.75+)
> - If you want to use react-native-mmkv 3.x.x, you need to enable the new architecture in your app (see ["Enable the New Architecture for Apps"](https://github.com/reactwg/react-native-new-architecture/blob/main/docs/enable-apps.md))
> - For React-Native 0.74.x, use react-native-mmkv 3.0.1. For React-Native 0.75.x and higher, use react-native-mmkv 3.0.2 or higher.
> - If you cannot use the new architecture yet, downgrade to react-native-mmkv 2.x.x for now.

## Benchmark

[StorageBenchmark](https://github.com/mrousavy/StorageBenchmark) compares popular storage libraries against each other by reading a value from storage for 1000 times:






MMKV vs other storage libraries: Reading a value from Storage 1000 times.

Measured in milliseconds on an iPhone 11 Pro, lower is better.


## Installation

### React Native

```sh
yarn add react-native-mmkv
cd ios && pod install
```

### Expo

```sh
npx expo install react-native-mmkv
npx expo prebuild
```

## Usage

### Create a new instance

To create a new instance of the MMKV storage, use the `MMKV` constructor. It is recommended that you re-use this instance throughout your entire app instead of creating a new instance each time, so `export` the `storage` object.

#### Default

```js
import { MMKV } from 'react-native-mmkv'

export const storage = new MMKV()
```

This creates a new storage instance using the default MMKV storage ID (`mmkv.default`).

#### App Groups or Extensions

If you want to share MMKV data between your app and other apps or app extensions in the same group, open `Info.plist` and create an `AppGroup` key with your app group's value. MMKV will then automatically store data inside the app group which can be read and written to from other apps or app extensions in the same group by making use of MMKV's multi processing mode.
See [Configuring App Groups](https://developer.apple.com/documentation/xcode/configuring-app-groups).

#### Customize

```js
import { MMKV, Mode } from 'react-native-mmkv'

export const storage = new MMKV({
id: `user-${userId}-storage`,
path: `${USER_DIRECTORY}/storage`,
encryptionKey: 'hunter2',
mode: Mode.MULTI_PROCESS,
readOnly: false
})
```

This creates a new storage instance using a custom MMKV storage ID. By using a custom storage ID, your storage is separated from the default MMKV storage of your app.

The following values can be configured:

* `id`: The MMKV instance's ID. If you want to use multiple instances, use different IDs. For example, you can separate the global app's storage and a logged-in user's storage. (required if `path` or `encryptionKey` fields are specified, otherwise defaults to: `'mmkv.default'`)
* `path`: The MMKV instance's root path. By default, MMKV stores file inside `$(Documents)/mmkv/`. You can customize MMKV's root directory on MMKV initialization (documentation: [iOS](https://github.com/Tencent/MMKV/wiki/iOS_advance#customize-location) / [Android](https://github.com/Tencent/MMKV/wiki/android_advance#customize-location))
* `encryptionKey`: The MMKV instance's encryption/decryption key. By default, MMKV stores all key-values in plain text on file, relying on iOS's/Android's sandbox to make sure the file is encrypted. Should you worry about information leaking, you can choose to encrypt MMKV. (documentation: [iOS](https://github.com/Tencent/MMKV/wiki/iOS_advance#encryption) / [Android](https://github.com/Tencent/MMKV/wiki/android_advance#encryption))
* `mode`: The MMKV's process behaviour - when set to `MULTI_PROCESS`, the MMKV instance will assume data can be changed from the outside (e.g. App Clips, Extensions or App Groups).
* `readOnly`: Whether this MMKV instance should be in read-only mode. This is typically more efficient and avoids unwanted writes to the data if not needed. Any call to `set(..)` will throw.

### Set

```js
storage.set('user.name', 'Marc')
storage.set('user.age', 21)
storage.set('is-mmkv-fast-asf', true)
```

### Get

```js
const username = storage.getString('user.name') // 'Marc'
const age = storage.getNumber('user.age') // 21
const isMmkvFastAsf = storage.getBoolean('is-mmkv-fast-asf') // true
```

### Hooks

```js
const [username, setUsername] = useMMKVString('user.name')
const [age, setAge] = useMMKVNumber('user.age')
const [isMmkvFastAsf, setIsMmkvFastAf] = useMMKVBoolean('is-mmkv-fast-asf')
```

### Keys

```js
// checking if a specific key exists
const hasUsername = storage.contains('user.name')

// getting all keys
const keys = storage.getAllKeys() // ['user.name', 'user.age', 'is-mmkv-fast-asf']

// delete a specific key + value
storage.delete('user.name')

// delete all keys
storage.clearAll()
```

### Objects

```js
const user = {
username: 'Marc',
age: 21
}

// Serialize the object into a JSON string
storage.set('user', JSON.stringify(user))

// Deserialize the JSON string into an object
const jsonUser = storage.getString('user') // { 'username': 'Marc', 'age': 21 }
const userObject = JSON.parse(jsonUser)
```

### Encryption

```js
// encrypt all data with a private key
storage.recrypt('hunter2')

// remove encryption
storage.recrypt(undefined)
```

### Buffers

```js
const buffer = new ArrayBuffer(3)
const dataWriter = new Uint8Array(buffer)
dataWriter[0] = 1
dataWriter[1] = 100
dataWriter[2] = 255
storage.set('someToken', buffer)

const buffer = storage.getBuffer('someToken')
console.log(buffer) // [1, 100, 255]
```

### Size

```js
// get size of MMKV storage in bytes
const size = storage.size
if (size >= 4096) {
// clean unused keys and clear memory cache
storage.trim()
}
```

## Testing with Jest or Vitest

A mocked MMKV instance is automatically used when testing with Jest or Vitest, so you will be able to use `new MMKV()` as per normal in your tests. Refer to [package/example/test/MMKV.test.ts](package/example/test/MMKV.test.ts) for an example using Jest.

## Documentation

* [Hooks](./docs/HOOKS.md)
* [Value-change Listeners](./docs/LISTENERS.md)
* [Migrate from AsyncStorage](./docs/MIGRATE_FROM_ASYNC_STORAGE.md)
* [Using MMKV with redux-persist](./docs/WRAPPER_REDUX.md)
* [Using MMKV with recoil](./docs/WRAPPER_RECOIL.md)
* [Using MMKV with mobx-persist-storage](./docs/WRAPPER_MOBX.md)
* [Using MMKV with mobx-persist](./docs/WRAPPER_MOBXPERSIST.md)
* [Using MMKV with zustand persist-middleware](./docs/WRAPPER_ZUSTAND_PERSIST_MIDDLEWARE.md)
* [Using MMKV with jotai](./docs/WRAPPER_JOTAI.md)
* [Using MMKV with react-query](./docs/WRAPPER_REACT_QUERY.md)
* [How is this library different from **react-native-mmkv-storage**?](https://github.com/mrousavy/react-native-mmkv/issues/100#issuecomment-886477361)

## LocalStorage and In-Memory Storage (Web)

If a user chooses to disable LocalStorage in their browser, the library will automatically provide a limited in-memory storage as an alternative. However, this in-memory storage won't persist data, and users may experience data loss if they refresh the page or close their browser. To optimize user experience, consider implementing a suitable solution within your app to address this scenario.

## Limitations

- react-native-mmkv V3 requires react-native 0.74 or higher.
- react-native-mmkv V3 requires [the new architecture](https://reactnative.dev/docs/the-new-architecture/landing-page)/TurboModules to be enabled.
- Since react-native-mmkv uses JSI for synchronous native method invocations, remote debugging (e.g. with Chrome) is no longer possible. Instead, you should use [Flipper](https://fbflipper.com) or [React DevTools](https://react.dev/learn/react-developer-tools).

## Integrations

### Flipper

Use [flipper-plugin-react-native-mmkv](https://github.com/muchobien/flipper-plugin-react-native-mmkv) to debug your MMKV storage using Flipper. You can also simply `console.log` an MMKV instance.

### Reactotron

Use [reactotron-react-native-mmkv](https://www.npmjs.com/package/reactotron-react-native-mmkv) to automatically log writes to your MMKV storage using Reactotron. [See the docs for how to setup this plugin with Reactotron.](https://www.npmjs.com/package/reactotron-react-native-mmkv)

## Community Discord

[**Join the Margelo Community Discord**](https://margelo.com/discord) to chat about react-native-mmkv or other Margelo libraries.

## Adopting at scale

react-native-mmkv is provided _as is_, I work on it in my free time.

If you're integrating react-native-mmkv in a production app, consider [funding this project](https://github.com/sponsors/mrousavy) and contact me to receive premium enterprise support, help with issues, prioritize bugfixes, request features, help at integrating react-native-mmkv, and more.

## Contributing

See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.

## License

MIT