Skip to content

Instantly share code, notes, and snippets.

@vuongngo
Created January 9, 2020 07:01
Show Gist options
  • Save vuongngo/7ac44fc4ecf607334c5b9ce659ffc026 to your computer and use it in GitHub Desktop.
Save vuongngo/7ac44fc4ecf607334c5b9ce659ffc026 to your computer and use it in GitHub Desktop.
const SET_INFO = 'SET_INFO';
const SET_ERROR = 'SET_ERROR';
const initialState = {
info: {},
error: null
};
const reducer = (state, action) => {
switch (action.type) {
case SET_INFO:
return {
...state,
info: action.payload.info
};
case SET_ERROR:
return {
...state,
error: action.payload.error
};
}
};
const useInfo = () => {
const [state, dispatch] = useReducer(reducer, initialState);
const setInfo = (values) => dispatch({
type: SET_INFO,
payload: {
info: values
}
});
const setError = (error) => dispatch({
type: SET_ERROR,
payload: {
error
}
});
return {
...state,
setInfo,
setError,
};
};
const useLocalInfo = () => {
const { info, setInfo, error, setError } = useState();
const { rehydrated } = useSession(info, setInfo, 'localInfoDemo');
return {
info,
setInfo,
error,
setError,
rehydrated,
};
};
const merge = (initialValue, hydratedValue) => {
if (!isObjectLike(initialValue)) {
return initialValue;
}
return {...hydratedValue, ...initialValue};
};
const useStorage = (state, setState, initialValue) => {
const [rehydrated, setRehydrated] = useState(false);
const [error, setError] = useState(null);
// rehydration
useEffect(() => {
localforage.getItem(config.key, (err, value) => {
if (err) {
setRehydrated(true);
return setError(err);
}
let mergedValue = rehydrated(value);
if (initialValue) {
mergedValue = merge(initialValue, mergedValue);
}
setState(mergedValue);
setRehydrated(true);
});
}, []);
// hydration
useEffect(() => {
if (isNil(state) || isEmpty(state)) {
localforage.removeItem(config.key);
}
localforage.setItem(config.key, hydrate(state));
}, [state]);
return {
rehydrated,
error,
};
};
const createMigration = (opts, data) => {
return new Promise((resolve, reject) => {
const key = `${opts.key}-version`;
localforage.getItem(key, (err, version) => {
if (version !== opts.version) {
data = opts.migrate(data);
localforage.setItem(opts.key, rehydrate(data), (err) => {
if (err) return reject(err);
localforage.setItem(key, opts.version, (err) => {
if (err) return reject(err);
return resolve(data);
});
})
} else {
resolve(data);
}
});
});
};
const config = {
key: '@session',
version: 1,
migrate: (state) => {
return {...state};
}
};
const useStorage = (state, setState) => {
const [rehydrated, setRehydrated] = useState(false);
const [error, setError] = useState(null);
// rehydration
useEffect(() => {
localforage.getItem(config.key, (err, value) => {
if (err) {
setRehydrated(true);
return setError(err);
}
const restoredValue = rehydrated(value);
if (typeof config.migrate === 'function') {
createMigration(config, restoredValue)
.then(data => setState(data))
.then(() => setRehydrated(true));
} else {
setState(restoredValue);
setRehydrated(true);
}
});
}, []);
// hydration
useEffect(() => {
if (isNil(state) || isEmpty(state)) {
localforage.removeItem(config.key);
}
localforage.setItem(config.key, hydrate(state));
}, [state]);
return {
rehydrated,
error,
};
};
const config = {
key: '@session',
transform: {
in: ({ name }) => ({ name }),
out: ({ name }) => ({ name, avatarUrl: '' })
}
}
const useStorage = (state, setState) => {
const [rehydrated, setRehydrated] = useState(false);
const [error, setError] = useState(null);
// rehydration
useEffect(() => {
localforage.getItem(config.key, (err, value) => {
if (err) {
setRehydrated(true);
return setError(err);
}
let restoredValue = rehydrated(value);
if (typeof config.transform?.out === 'function') {
restoredValue = config.transform.out(restoredValue);
}
setState(restoredValue);
setRehydrated(true);
});
}, []);
// hydration
useEffect(() => {
if (isNil(state) || isEmpty(state)) {
localforage.removeItem(config.key);
}
let data;
if (typeof config.transform?.in === 'function') {
data = config.transform.in(state);
}
localforage.setItem(config.key, hydrate(data));
}, [state]);
return {
rehydrated,
error,
};
};
import { useEffect, useState, useReducer } from 'react';
import { isEmpty, isNil } from 'ramda';
const isObjectLiked = (value) =>
value.constructor.name == "Array" ||
value.constructor.name == "Object";
const rehydrate = (value, defaultValue) => {
if (!value) return;
if (value === 'false') str = false;
if (value === 'true') str = true;
if (!isObjectLiked(value)) {
return value;
}
try {
const parse = JSON.parse(value);
return parse;
} catch (err) {
return defaultValue;
}
}
const hydrate = (value) => {
if (!isObjectLiked(value)) {
return value;
}
return JSON.stringify(state);
}
// useSession hook
const config = {
key: '@session',
}
const useSession = (state, setState) => {
const [hydrated, setHydrated] = useState(false);
// rehydration
useEffect(() => {
const value = sessionStorage.getItem(config.key);
setState(rehydrated(value));
setHydrated(true);
}, []);
// hydration
useEffect(() => {
if (isNil(state) || isEmpty(state)) {
sessionStorage.removeItem(config.key);
}
sessionStorage.setItem(hydrate(state));
}, [state]);
return {
hydrated,
}
};
import localforage from 'localforage';
const useStorage = (state, setState) => {
const [rehydrated, setRehydrated] = useState(false);
const [error, setError] = useState(null);
// rehydration
useEffect(() => {
localforage.getItem(config.key, (err, value) => {
if (err) {
setRehydrated(true);
return setError(err);
}
setState(rehydrated(value));
setRehydrated(true);
});
}, []);
// hydration
useEffect(() => {
if (isNil(state) || isEmpty(state)) {
localforage.removeItem(config.key);
}
localforage.setItem(config.key, hydrate(state));
}, [state]);
return {
rehydrated,
error,
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment