Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 0327a1f

Browse files
Merge pull request zoltantothcom#55 from ixnv/save-user-preferences-to-localstorage
Save user preferences to localStorage
2 parents a898318 + 6d061a1 commit 0327a1f

File tree

5 files changed

+129
-4
lines changed

5 files changed

+129
-4
lines changed

‎.eslintrc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
"env": {
55
"browser": true,
66
"node": true,
7-
"jest": true
7+
"jest": true,
8+
"es6": true
89
},
910
"settings": {
1011
"react": {

‎__tests__/localStorage.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import {
2+
loadState,
3+
saveState
4+
} from '../src/helpers/localStorage';
5+
6+
describe('LocalStorage utilities', () => {
7+
beforeEach(() => {
8+
window.localStorage.clear();
9+
});
10+
11+
const data = {
12+
foo: 1
13+
};
14+
15+
it('should save and load state', () => {
16+
saveState(data);
17+
18+
const state = loadState();
19+
expect(state).toMatchObject(data);
20+
});
21+
22+
it('should not throw exceptions if localStorage is undefined', () => {
23+
Reflect.deleteProperty(window, 'localStorage');
24+
25+
expect(saveState(data)).toBeUndefined();
26+
expect(loadState()).toBeUndefined();
27+
});
28+
});

‎__tests__/store/store.test.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import {
2+
TOGGLE_JS,
3+
TOGGLE_MODE
4+
} from '../../src/static/constants/actions';
5+
import { loadState, saveState } from '../../src/helpers/localStorage';
6+
7+
describe('Store', () => {
8+
beforeEach(() => {
9+
jest.resetModules();
10+
window.localStorage.clear();
11+
});
12+
13+
it('should work without saved state', () => {
14+
const {
15+
default: store,
16+
initialState
17+
} = require('../../src/store');
18+
19+
expect(store.getState()).toMatchObject(initialState);
20+
});
21+
22+
it('should load saved state from localStorage', () => {
23+
const savedState = {
24+
mode: 'light',
25+
js: 'es6'
26+
};
27+
saveState(savedState);
28+
29+
const state = require('../../src/store').default.getState();
30+
expect(state.mode).toBe('light');
31+
expect(state.js).toBe('es6');
32+
});
33+
34+
it('should save state to localStorage', () => {
35+
const toggleJSAction = {
36+
type: TOGGLE_JS,
37+
payload: 'es6'
38+
};
39+
40+
const toggleModeAction = {
41+
type: TOGGLE_MODE,
42+
payload: 'light'
43+
};
44+
45+
const {
46+
default: store
47+
} = require('../../src/store');
48+
49+
store.dispatch(toggleJSAction);
50+
store.dispatch(toggleModeAction);
51+
52+
expect(loadState()).toMatchObject({
53+
mode: 'light',
54+
js: 'es6'
55+
});
56+
});
57+
});

‎src/helpers/localStorage.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
export const loadState = () => {
2+
try {
3+
const serializedState = JSON.parse(localStorage.getItem('state'));
4+
5+
return serializedState === null ? undefined : serializedState;
6+
} catch (e) {
7+
return undefined;
8+
}
9+
};
10+
11+
export const saveState = (state) => {
12+
try {
13+
const serializedState = JSON.stringify(state);
14+
localStorage.setItem('state', serializedState);
15+
} catch (e) {
16+
return undefined;
17+
}
18+
};

‎src/store/index.js

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
1-
import { createStore, applyMiddleware, compose } from 'redux';
1+
import {
2+
createStore,
3+
applyMiddleware,
4+
compose
5+
} from 'redux';
26
const uuid = require('uuid/v4');
37
import reducer from '../reducers/index';
48
import patterns from '../static/patterns';
59
import middleware from '../middleware';
10+
import {
11+
loadState,
12+
saveState
13+
} from '../helpers/localStorage';
614

715
export const answers = patterns.map(pattern => ({
816
...pattern,
@@ -18,16 +26,29 @@ export const initialProgress = {
1826
current: answers[0]
1927
};
2028

21-
const initialState = {
29+
exportconst initialState = {
2230
js: 'es5',
2331
mode: 'dark',
2432
intro: true,
2533
patterns: answers,
2634
progress: initialProgress
2735
};
2836

37+
const state = {
38+
...initialState,
39+
...loadState()
40+
};
41+
2942
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
3043

31-
const store = createStore(reducer, initialState, composeEnhancers(applyMiddleware(...middleware)));
44+
const store = createStore(reducer, state, composeEnhancers(applyMiddleware(...middleware)));
45+
46+
store.subscribe(() => {
47+
const currentState = store.getState();
48+
saveState({
49+
mode: currentState.mode,
50+
js: currentState.js
51+
});
52+
});
3253

3354
export default store;

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /