From bb3093181de641bd8abbff0a2dd86bdba399cccc Mon Sep 17 00:00:00 2001 From: Justin Edelson Date: Tue, 20 Jun 2023 15:47:21 -0400 Subject: [PATCH] support custom serialization/deserialization. fixes #75 --- README.md | 20 ++++++++++++++++++++ src/index.ts | 14 ++++++++++---- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 126d77a..e952109 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,10 @@ import { recoilPersist } from 'recoil-persist' const { persistAtom } = recoilPersist({ key: 'recoil-persist', // this key is using to store data in local storage storage: localStorage, // configurate which storage will be used to store the data + converter: { // configurate how values will be serialized/deserialized in storage + parse: (value) => JSON.parse, + stringify: (value) => JSON.stringify + } }) ``` @@ -176,6 +180,22 @@ type config.storage = Storage Set `config.storage` with `sessionStorage` or other `Storage` implementation to change storage target. Otherwise `localStorage` is used (default). +```js +type config.converter = { + stringify: (value: any) => string + parse: (value: string) => any +} +``` + +Set `config.converter` to an object which implements both `stringify` and `parse` functions to convert state values to and from strings. One use of this would be to wrap the standard `JSON.stringify` and `JSON.parse` functions, e.g. to insert your own `reviver` and `replacer` functions: + +```js +{ + parse: (value) => JSON.parse(value, myCustomReviver), + stringify: (value) => JSON.stringify(value, myCustomReplacer) +}; +``` + ## Migration from version 1.x.x to 2.x.x The API changed from version 1.x.x. diff --git a/src/index.ts b/src/index.ts index 45d1871..f0c75e2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,9 +6,15 @@ export interface PersistStorage { getItem(key: string): null | string | Promise } +export interface PersistConverter { + stringify: (value: any) => string + parse: (value: string) => any +} + export interface PersistConfiguration { key?: string storage?: PersistStorage + converter?: PersistConverter } /** @@ -27,7 +33,7 @@ export const recoilPersist = ( } } - const { key = 'recoil-persist', storage = localStorage } = config + const { key = 'recoil-persist', storage = localStorage, converter = JSON } = config const persistAtom: AtomEffect = ({ onSet, node, trigger, setSelf }) => { if (trigger === 'get') { @@ -89,7 +95,7 @@ export const recoilPersist = ( return {} } try { - return JSON.parse(state) + return converter.parse(state) } catch (e) { console.error(e) return {} @@ -99,9 +105,9 @@ export const recoilPersist = ( const setState = (state: any): void => { try { if (typeof storage.mergeItem === 'function') { - storage.mergeItem(key, JSON.stringify(state)) + storage.mergeItem(key, converter.stringify(state)) } else { - storage.setItem(key, JSON.stringify(state)) + storage.setItem(key, converter.stringify(state)) } } catch (e) { console.error(e)