Skip to content

Commit

Permalink
feat: 🎸 implement useLocalStorage without events
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich committed Oct 30, 2018
1 parent d82a16e commit d211722
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 28 deletions.
14 changes: 7 additions & 7 deletions src/__stories__/useLocalStorage.story.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import {storiesOf} from '@storybook/react';
import * as React from 'react';
import {useLocalStorage} from '..';
import ShowDocs from '../util/ShowDocs';

const Demo = () => {
const value = useLocalStorage('key');
const [value, setValue] = useLocalStorage('hello-key', 'foo');

return (
<div>
<div>Value: {value}</div>
<button onClick={() => {(window.localStorage as any)['key'] = String(Date.now())}}>Update</button>
<button onClick={() => setValue('bar')}>bar</button>
<button onClick={() => setValue('baz')}>baz</button>
</div>
);
};

// storiesOf('useLocalStorage', module)
storiesOf('useLocalStorage', module)
// .add('Docs', () => <ShowDocs md={require('../../docs/useLocalStorage.md')} />)
// .add('Demo', () =>
// <Demo/>
// )
.add('Demo', () =>
<Demo/>
)
2 changes: 1 addition & 1 deletion src/react.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';

export type UseState = <T>(initialState: T) => [T, (newState: T) => void];
export type UseState = <T>(initialState: T | (() => T)) => [T, (newState: T) => void];
export const useState: UseState = (React as any).useState;

export type UseEffect = (didUpdate: () => ((() => void) | void), params?: any[]) => void;
Expand Down
46 changes: 26 additions & 20 deletions src/useLocalStorage.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,41 @@
import {useState, useEffect} from './react';
import {on, off} from './util';
// import {on, off} from './util';

const isClient = typeof window === 'object';

const useLocalStorage = (key: string): string | undefined => {
const useLocalStorage = <T>(key: string, initialValue?: T, raw?: boolean): [T, (value: T) => void] => {
if (!isClient) {
return undefined;
return [initialValue as T, () => {}];
}

const [state, setState] = useState<string | undefined>(undefined);

useEffect(() => {
const [state, setState] = useState<T>(() => {
try {
setState(localStorage[key]);
} catch {}

const onChange = (event) => {
console.log('onChange')
if (event.key === key) {
setState(event.newValue);
const localStorageValue = localStorage.getItem(key);
if (typeof localStorageValue !== 'string') {
localStorage.setItem(key, raw ? String(initialValue) : JSON.stringify(initialValue));
return initialValue;
} else {
return raw ? localStorageValue : JSON.parse(localStorageValue || 'null');
}
} catch {
// If user is in private mode or has storage restriction
// localStorage can throw. JSON.parse and JSON.stringify
// cat throw, too.
return initialValue;
}
});

on(window, 'storage', onChange);

return () => {
off(window, 'storage', onChange);
};
}, [key]);
useEffect(() => {
try {
const serializedState = raw ? String(state) : JSON.stringify(state);
localStorage.setItem(key, serializedState);
} catch {
// If user is in private mode or has storage restriction
// localStorage can throw. Also JSON.stringify can throw.
}
});

return state;
return [state, setState];
};

export default useLocalStorage;

0 comments on commit d211722

Please sign in to comment.