From 9e1728038976686f679e4bf867c8150a66d14293 Mon Sep 17 00:00:00 2001 From: Alexander Kurganov Date: Sat, 3 Oct 2020 17:44:55 +0300 Subject: [PATCH] feat: Support SSR. Closes #196 --- __tests__/create-persisted-state.test.tsx | 28 +++++++++++++-- src/utils/create-web-storage.ts | 44 +++++++++++++---------- src/utils/get-persisted-value.ts | 2 +- 3 files changed, 52 insertions(+), 22 deletions(-) diff --git a/__tests__/create-persisted-state.test.tsx b/__tests__/create-persisted-state.test.tsx index 44c68400..985d4bcd 100644 --- a/__tests__/create-persisted-state.test.tsx +++ b/__tests__/create-persisted-state.test.tsx @@ -1,10 +1,11 @@ import { createPersistedState } from '../src' import storage from '../src/storages/local-storage' +import createStorage from '../src/utils/create-web-storage' import { renderHook, cleanup, act } from '@testing-library/react-hooks' -const [usePersistedState, clear] = createPersistedState('test', storage) - describe('hook defined correctly', () => { + const [usePersistedState, clear] = createPersistedState('test', storage) + beforeEach(() => { cleanup() clear() @@ -32,3 +33,26 @@ describe('hook defined correctly', () => { expect(localStorage.__STORE__['persisted_state_hook:test']).toEqual(expected) }) }) + +describe('hook works on SSR', () => { + const testingSSRStorage = createStorage(undefined as unknown as Storage) + const [usePersistedState, clear] = createPersistedState('test', testingSSRStorage) + + it('is callable', () => { + const { result } = renderHook(() => usePersistedState('foo', 'bar')) + + expect(usePersistedState).toBeDefined() + expect(clear).toBeDefined() + expect(result.current).toBeDefined() + }) + + it('localstorage called correctly', () => { + const { result } = renderHook(() => usePersistedState('foo', 'bar')) + + act(() => { + result.current[1]('baz') + }) + + expect(result.current[0]).toBe('baz') + }) +}) diff --git a/src/utils/create-web-storage.ts b/src/utils/create-web-storage.ts index 311b19a2..3cc9badf 100644 --- a/src/utils/create-web-storage.ts +++ b/src/utils/create-web-storage.ts @@ -39,12 +39,12 @@ export default (storage: globalThis.Storage): Storage => ({ if (Array.isArray(keys)) { keys.forEach(key => { - const item = storage.getItem(key) + const item = typeof storage !== 'undefined' ? storage.getItem(key) : undefined if (item) result[key] = item }) } else { - const item = storage.getItem(keys) + const item = typeof storage !== 'undefined' ? storage.getItem(keys) : undefined if (item) result[keys] = item } @@ -55,44 +55,50 @@ export default (storage: globalThis.Storage): Storage => ({ const changes: { [key: string]: StorageChange } = {} Object.entries(items).forEach(([key, value]) => { - const oldValue = storage.getItem(key) + const oldValue = typeof storage !== 'undefined' ? storage.getItem(key) : undefined - storage.setItem(key, value) + if (typeof storage !== 'undefined') { + storage.setItem(key, value) - changes[key] = { - oldValue, - newValue: value, + changes[key] = { + oldValue, + newValue: value, + } } }) - fireStorageEvent(changes) + if (Object.keys(changes).length > 0) fireStorageEvent(changes) }, remove: keys => { const changes: { [key: string]: StorageChange } = {} if (Array.isArray(keys)) { keys.forEach(key => { - const oldValue = storage.getItem(key) + const oldValue = typeof storage !== 'undefined' ? storage.getItem(key) : undefined - storage.removeItem(key) + if (typeof storage !== 'undefined') { + storage.removeItem(key) - changes[key] = { - oldValue, - newValue: null, + changes[key] = { + oldValue, + newValue: null, + } } }) } else { - const oldValue = storage.getItem(keys) + const oldValue = typeof storage !== 'undefined' ? storage.getItem(keys) : undefined - storage.removeItem(keys) + if (typeof storage !== 'undefined') { + storage.removeItem(keys) - changes[keys] = { - oldValue, - newValue: null, + changes[keys] = { + oldValue, + newValue: null, + } } } - fireStorageEvent(changes) + if (Object.keys(changes).length > 0) fireStorageEvent(changes) }, onChanged, }) diff --git a/src/utils/get-persisted-value.ts b/src/utils/get-persisted-value.ts index a89c9c3d..a64901de 100644 --- a/src/utils/get-persisted-value.ts +++ b/src/utils/get-persisted-value.ts @@ -1,6 +1,6 @@ import isFunction from './is-function' -export default function(key:string, initialValue: T | (() => T), persist: string): T { +export default function(key:string, initialValue: T | (() => T), persist?: string): T { let initialPersist: { [x: string]: unknown } try {