Skip to content

Commit

Permalink
💥 Fix use local storage for ssr (#129)
Browse files Browse the repository at this point in the history
* Add useLocalStorage tests

* Add check for window in useLocalStorage
  • Loading branch information
nezouse authored Apr 3, 2021
1 parent 9a516ca commit 47652a3
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 9 deletions.
5 changes: 5 additions & 0 deletions .changeset/light-carrots-jog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@usedapp/core": patch
---

💥 Fix useLocalStorage for serverSide rendering
11 changes: 6 additions & 5 deletions packages/core/.mocharc.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"spec": "test/**/*.test.{ts,tsx}",
"require": "ts-node/register",
"watchExtensions": "ts",
"extension": "ts",
"timeout": 3000
"spec": "test/**/*.test.{ts,tsx}",
"require": "ts-node/register",
"watchExtensions": "ts",
"extension": "ts",
"timeout": 3000,
"file": "./test/setup.ts"
}
1 change: 1 addition & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"jsdom": "^16.4.0",
"jsdom-global": "^3.0.2",
"mocha": "^8.2.1",
"mock-local-storage": "^1.1.17",
"prettier": "^2.1.2",
"ts-node": "^9.1.1",
"typescript": "^4.1.3"
Expand Down
8 changes: 5 additions & 3 deletions packages/core/src/hooks/useLocalStorage.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { useEffect, useState } from 'react'

function getItem(key: string) {
if (typeof window === 'undefined') {
return null
}

const item = window.localStorage.getItem(key)
let result
if (item !== null) {
try {
result = JSON.parse(item)
return JSON.parse(item)
} catch {
// ignore error
}
}
return result
}

function setItem(key: string, value: any) {
Expand Down
87 changes: 87 additions & 0 deletions packages/core/test/hooks/useLocalStorage.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { act, renderHook } from '@testing-library/react-hooks'
import { expect } from 'chai'
import { useLocalStorage } from '../../src/hooks/useLocalStorage'

describe('useLocalStorage', () => {
beforeEach(() => {
window.localStorage.clear()
})

function render() {
let key = 'foo'
const result = renderHook(() => useLocalStorage(key))
return {
getValue: () => result.result.current[0],
setValue: (value: any) => act(() => result.result.current[1](value)),
setKey: (value: string) => {
key = value
result.rerender()
},
}
}

it('returns undefined for empty storage', () => {
const { getValue } = render()
expect(getValue()).to.equal(undefined)
})

it('parses existing values', () => {
window.localStorage.setItem('foo', JSON.stringify({ a: 1 }))
const { getValue } = render()
expect(getValue()).to.deep.equal({ a: 1 })
})

it('caches results', () => {
window.localStorage.setItem('foo', JSON.stringify({ a: 1 }))
const { getValue } = render()
expect(getValue()).to.deep.equal({ a: 1 })
window.localStorage.setItem('foo', JSON.stringify({ a: 2 }))
expect(getValue()).to.deep.equal({ a: 1 })
})

it('returns undefined when cannot parse', () => {
window.localStorage.setItem('foo', 'x{}y')
const { getValue } = render()
expect(getValue()).to.equal(undefined)
})

it('modifies the localStorage and returns a the new value', () => {
const { getValue, setValue } = render()
expect(getValue()).to.equal(undefined)
setValue({ a: 1 })
expect(window.localStorage.getItem('foo')).to.equal('{"a":1}')
expect(getValue()).to.deep.equal({ a: 1 })
})

it('can remove the item by setting undefined', () => {
window.localStorage.setItem('foo', 'true')
const { getValue, setValue } = render()
expect(getValue()).to.equal(true)
setValue(undefined)
expect(getValue()).to.equal(undefined)
expect(window.localStorage.getItem('foo')).to.equal(null)
})

it('can change keys', () => {
window.localStorage.setItem('foo', 'true')
const { getValue, setKey } = render()
expect(getValue()).to.equal(true)
setKey('bar')
expect(getValue()).to.equal(undefined)
expect(window.localStorage.getItem('foo')).to.equal('true')
expect(window.localStorage.getItem('bar')).to.equal(null)
})

it('can change keys and modify the other value', () => {
window.localStorage.setItem('foo', 'true')
window.localStorage.setItem('bar', 'false')
const { getValue, setValue, setKey } = render()
expect(getValue()).to.equal(true)
setValue(123)
setKey('bar')
expect(getValue()).to.equal(false)
setValue(456)
expect(window.localStorage.getItem('foo')).to.equal('123')
expect(window.localStorage.getItem('bar')).to.equal('456')
})
})
2 changes: 2 additions & 0 deletions packages/core/test/setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import 'jsdom-global/register'
import 'mock-local-storage'
15 changes: 14 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3457,6 +3457,11 @@ core-js-pure@^3.0.0, core-js-pure@^3.0.1:
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.10.0.tgz#dab9d6b141779b622b40567e7a536d2276646c15"
integrity sha512-CC582enhrFZStO4F8lGI7QL3SYx7/AIRc+IdSi3btrQGrVsTawo5K/crmKbRrQ+MOMhNX4v+PATn0k2NN6wI7A==

core-js@^0.8.3:
version "0.8.4"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-0.8.4.tgz#c22665f1e0d1b9c3c5e1b08dabd1f108695e4fcf"
integrity sha1-wiZl8eDRucPF4bCNq9HxCGleT88=

core-js@^2.4.0, core-js@^2.5.0:
version "2.6.12"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec"
Expand Down Expand Up @@ -5486,7 +5491,7 @@ glob@7.1.6, glob@^7.0.3, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@~7.1.6:
once "^1.3.0"
path-is-absolute "^1.0.0"

global@~4.4.0:
global@^4.3.2, global@~4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406"
integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==
Expand Down Expand Up @@ -7512,6 +7517,14 @@ mock-fs@^4.1.0:
resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.13.0.tgz#31c02263673ec3789f90eb7b6963676aa407a598"
integrity sha512-DD0vOdofJdoaRNtnWcrXe6RQbpHkPPmtqGq14uRX0F8ZKJ5nv89CVTYl/BZdppDxBDaV0hl75htg3abpEWlPZA==

mock-local-storage@^1.1.17:
version "1.1.17"
resolved "https://registry.yarnpkg.com/mock-local-storage/-/mock-local-storage-1.1.17.tgz#13325dad4e3b696374c2984fa8af33941f54239e"
integrity sha512-vF5571cY3N/XFw8Oxr+0HmY6PedvO6i2IZrpnDV35sh7alhrh1RYYFZzItuh5OhJrQoulNSruiw1KHk5QB/EQg==
dependencies:
core-js "^0.8.3"
global "^4.3.2"

move-concurrently@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"
Expand Down

0 comments on commit 47652a3

Please sign in to comment.