From 90823d6656b7e06c10a024ed393043acf6654cf7 Mon Sep 17 00:00:00 2001 From: Alexander Gabriel Date: Sun, 7 Jul 2019 22:57:36 +0200 Subject: [PATCH 1/5] (fix): do not error if 'window' is undefined - in certain environments like Node, 'window' will not be defined and so will cause mst-persist to error out on its check for localStorge, even if a different storage engine were configured - this fix enables usage in Node environments, supporting usage like hydrating server-side --- src/index.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index c9f4e33..bee49b2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -16,7 +16,12 @@ type StrToAnyMap = {[key: string]: any} export const persist: IArgs = (name, store, options = {}) => { let {storage, jsonify, whitelist, blacklist} = options - if (typeof window.localStorage !== 'undefined' && (!storage || storage === window.localStorage)) { + // use AsyncLocalStorage by default (or if localStorage was passed in) + if ( + typeof window !== 'undefined' && + typeof window.localStorage !== 'undefined' && + (!storage || storage === window.localStorage) + ) { storage = AsyncLocalStorage } if (!jsonify) { jsonify = true } // default to true like mobx-persist From 14b77b615019479f72e50fc9b577ff4b8ca5a734 Mon Sep 17 00:00:00 2001 From: Anton Gilgur Date: Sat, 13 Jul 2019 21:24:51 -0400 Subject: [PATCH 2/5] (fix): throw an error if no storage is configured - if the localStorage default is unsupported in the current environment (e.g. Node), then it should throw with a specific error instead of continuing and unexpectedly throwing on getItem - will still error out, so not a "fix" in that sense, but it now will throw a better, more understandable error --- src/index.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/index.ts b/src/index.ts index bee49b2..9d0cbff 100644 --- a/src/index.ts +++ b/src/index.ts @@ -24,6 +24,12 @@ export const persist: IArgs = (name, store, options = {}) => { ) { storage = AsyncLocalStorage } + if (!storage) { + return Promise.reject('localStorage (the default storage engine) is not ' + + 'supported in this environment. Please configure a different storage ' + + 'engine via the `storage:` option.') + } + if (!jsonify) { jsonify = true } // default to true like mobx-persist const whitelistDict = arrToDict(whitelist) const blacklistDict = arrToDict(blacklist) From 309363bbe6b664d0958a93d6bfd0bf5da4204956 Mon Sep 17 00:00:00 2001 From: Anton Gilgur Date: Sat, 27 Jul 2019 16:54:28 -0400 Subject: [PATCH 3/5] (docs): re-word storage section for clarity --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5ff2153..242d84e 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,10 @@ persist('some', someStore, { - **key** *string* The key of your storage engine that you want to persist to. - **store** *MST store* The store to be persisted. - **options** *object* Additional configuration options. - - **storage** *[localForage](https://github.com/localForage/localForage) / AsyncStorage / localStorage* [localForage](https://github.com/localForage/localForage)-style storage API. localStorage for Web (default), AsyncStorage for React Native. + - **storage** *[localForage](https://github.com/localForage/localForage) / AsyncStorage / localStorage* + Any Storage Engine that has a Promise-style API similar to [`localForage`](https://github.com/localForage/localForage). + The default is `localStorage`, which has a built-in adaptor to make it support Promises. + For React Native, one may configure `AsyncStorage` instead. - **jsonify** *bool* Enables serialization as JSON (default: `true`). - **whitelist** *Array\* Only these keys will be persisted (defaults to all keys). - **blacklist** *Array\* These keys will not be persisted (defaults to all keys). From cfe162bade79d987e7dfe697bb03803cd3ccf906 Mon Sep 17 00:00:00 2001 From: Anton Gilgur Date: Sat, 27 Jul 2019 16:57:07 -0400 Subject: [PATCH 4/5] (docs): note redux-persist's Storage Engines compatibility - redux-persist's Storage Engines all follow the same localForage-style async Promise API, so they should all be compatible with mst-persist as well - docs should mention this as the interoperability adds many more usage options for developers - e.g. using node-storage or cookie-storage for Node or universal apps, which should now work without bugs --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 242d84e..40a8164 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,8 @@ persist('some', someStore, { Any Storage Engine that has a Promise-style API similar to [`localForage`](https://github.com/localForage/localForage). The default is `localStorage`, which has a built-in adaptor to make it support Promises. For React Native, one may configure `AsyncStorage` instead. +
+ Any of [`redux-persist`'s Storage Engines](https://github.com/rt2zz/redux-persist#storage-engines) should also be compatible with `mst-persist`. - **jsonify** *bool* Enables serialization as JSON (default: `true`). - **whitelist** *Array\* Only these keys will be persisted (defaults to all keys). - **blacklist** *Array\* These keys will not be persisted (defaults to all keys). From 6cdd55ec066947fb98836e04fe3ec65d0d333e08 Mon Sep 17 00:00:00 2001 From: Anton Gilgur Date: Sat, 27 Jul 2019 17:12:31 -0400 Subject: [PATCH 5/5] (docs): add section on Node and SSR Usage - note that one can hydrate server-side with Node and give some example storage engines one may use for that purpose - note that server-side hydartion can be skipped for certain use cases like SSR and give example for how to do so --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.md b/README.md index 40a8164..ae2308f 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,21 @@ persist('some', someStore, { - returns a void Promise +### Node and Server-Side Rendering (SSR) Usage + +Node environments are supported so long as you configure a Storage Engine that supports Node, such as [`redux-persist-node-storage`](https://github.com/pellejacobs/redux-persist-node-storage), [`redux-persist-cookie-storage`](https://github.com/abersager/redux-persist-cookie-storage), etc. +This allows you to hydrate your store server-side. + +For SSR though, you may not want to hydrate your store server-side, so in that case you can call `persist` conditionally: + +```javascript +if (typeof window !== 'undefined') { // window is undefined in Node + persist(...) +} +``` + +With this conditional check, your store will only be hydrated client-side. + ## Examples None yet, but can take a look at [agilgur5/react-native-manga-reader-app](https://github.com/agilgur5/react-native-manga-reader-app) which uses it in production.