react-native-mmkv
Version:
The fastest key/value storage for React Native. ~30x faster than AsyncStorage! Works on Android, iOS and Web.
198 lines (189 loc) • 6.57 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useMMKV = useMMKV;
exports.useMMKVBuffer = exports.useMMKVBoolean = void 0;
exports.useMMKVListener = useMMKVListener;
exports.useMMKVNumber = void 0;
exports.useMMKVObject = useMMKVObject;
exports.useMMKVString = void 0;
var _react = require("react");
var _MMKV = require("./MMKV");
function isConfigurationEqual(left, right) {
if (left == null || right == null) return left == null && right == null;
return left.encryptionKey === right.encryptionKey && left.id === right.id && left.path === right.path && left.mode === right.mode;
}
let defaultInstance = null;
function getDefaultInstance() {
if (defaultInstance == null) {
defaultInstance = new _MMKV.MMKV();
}
return defaultInstance;
}
/**
* Use the default, shared MMKV instance.
*/
/**
* Use a custom MMKV instance with the given configuration.
* @param configuration The configuration to initialize the MMKV instance with. Does not have to be memoized.
*/
function useMMKV(configuration) {
const instance = (0, _react.useRef)();
const lastConfiguration = (0, _react.useRef)();
if (configuration == null) return getDefaultInstance();
if (instance.current == null || !isConfigurationEqual(lastConfiguration.current, configuration)) {
lastConfiguration.current = configuration;
instance.current = new _MMKV.MMKV(configuration);
}
return instance.current;
}
function createMMKVHook(getter) {
return (key, instance) => {
const mmkv = instance ?? getDefaultInstance();
const [bump, setBump] = (0, _react.useState)(0);
const value = (0, _react.useMemo)(() => {
// bump is here as an additional outside dependency, so this useMemo
// re-computes the value each time bump changes, effectively acting as a hint
// that the outside value (storage) has changed. setting bump refreshes this value.
bump;
return getter(mmkv, key);
}, [mmkv, key, bump]);
// update value by user set
const set = (0, _react.useCallback)(v => {
const newValue = typeof v === 'function' ? v(getter(mmkv, key)) : v;
switch (typeof newValue) {
case 'number':
case 'string':
case 'boolean':
mmkv.set(key, newValue);
break;
case 'undefined':
mmkv.delete(key);
break;
case 'object':
if (newValue instanceof ArrayBuffer) {
mmkv.set(key, newValue);
break;
} else {
throw new Error(`MMKV: Type object (${newValue}) is not supported!`);
}
default:
throw new Error(`MMKV: Type ${typeof newValue} is not supported!`);
}
}, [key, mmkv]);
// update value if it changes somewhere else (second hook, same key)
(0, _react.useEffect)(() => {
const listener = mmkv.addOnValueChangedListener(changedKey => {
if (changedKey === key) {
setBump(b => b + 1);
}
});
return () => listener.remove();
}, [key, mmkv]);
return [value, set];
};
}
/**
* Use the string value of the given `key` from the given MMKV storage instance.
*
* If no instance is provided, a shared default instance will be used.
*
* @example
* ```ts
* const [username, setUsername] = useMMKVString("user.name")
* ```
*/
const useMMKVString = exports.useMMKVString = createMMKVHook((instance, key) => instance.getString(key));
/**
* Use the number value of the given `key` from the given MMKV storage instance.
*
* If no instance is provided, a shared default instance will be used.
*
* @example
* ```ts
* const [age, setAge] = useMMKVNumber("user.age")
* ```
*/
const useMMKVNumber = exports.useMMKVNumber = createMMKVHook((instance, key) => instance.getNumber(key));
/**
* Use the boolean value of the given `key` from the given MMKV storage instance.
*
* If no instance is provided, a shared default instance will be used.
*
* @example
* ```ts
* const [isPremiumAccount, setIsPremiumAccount] = useMMKVBoolean("user.isPremium")
* ```
*/
const useMMKVBoolean = exports.useMMKVBoolean = createMMKVHook((instance, key) => instance.getBoolean(key));
/**
* Use the buffer value (unsigned 8-bit (0-255)) of the given `key` from the given MMKV storage instance.
*
* If no instance is provided, a shared default instance will be used.
*
* @example
* ```ts
* const [privateKey, setPrivateKey] = useMMKVBuffer("user.privateKey")
* ```
*/
const useMMKVBuffer = exports.useMMKVBuffer = createMMKVHook((instance, key) => instance.getBuffer(key));
/**
* Use an object value of the given `key` from the given MMKV storage instance.
*
* If no instance is provided, a shared default instance will be used.
*
* The object will be serialized using `JSON`.
*
* @example
* ```ts
* const [user, setUser] = useMMKVObject<User>("user")
* ```
*/
function useMMKVObject(key, instance) {
const [json, setJson] = useMMKVString(key, instance);
const value = (0, _react.useMemo)(() => {
if (json == null) return undefined;
return JSON.parse(json);
}, [json]);
const setValue = (0, _react.useCallback)(v => {
if (v instanceof Function) {
setJson(currentJson => {
const currentValue = currentJson != null ? JSON.parse(currentJson) : undefined;
const newValue = v(currentValue);
// Store the Object as a serialized Value or clear the value
return newValue != null ? JSON.stringify(newValue) : undefined;
});
} else {
// Store the Object as a serialized Value or clear the value
const newValue = v != null ? JSON.stringify(v) : undefined;
setJson(newValue);
}
}, [setJson]);
return [value, setValue];
}
/**
* Listen for changes in the given MMKV storage instance.
* If no instance is passed, the default instance will be used.
* @param valueChangedListener The function to call whenever a value inside the storage instance changes
* @param instance The instance to listen to changes to (or the default instance)
*
* @example
* ```ts
* useMMKVListener((key) => {
* console.log(`Value for "${key}" changed!`)
* })
* ```
*/
function useMMKVListener(valueChangedListener, instance) {
const ref = (0, _react.useRef)(valueChangedListener);
ref.current = valueChangedListener;
const mmkv = instance ?? getDefaultInstance();
(0, _react.useEffect)(() => {
const listener = mmkv.addOnValueChangedListener(changedKey => {
ref.current(changedKey);
});
return () => listener.remove();
}, [mmkv]);
}
//# sourceMappingURL=hooks.js.map
;