Skip to content

Instantly share code, notes, and snippets.

@ClaireNeveu
Last active October 6, 2022 21:03
Show Gist options
  • Save ClaireNeveu/e91f920c71058a915309bdb667aaa667 to your computer and use it in GitHub Desktop.
Save ClaireNeveu/e91f920c71058a915309bdb667aaa667 to your computer and use it in GitHub Desktop.
useSettings Skeleton
import { createContext, ReactChildren, useContext, useEffect, useMemo, useState } from 'react';
import { Type } from 'io-ts';
import { useNavigate } from 'react-router-dom-v5-compat';
/*
* UserSettingsTable contains all the settings for a user
* across the application. Each key identifies a unique part
* of the interface to store settings for.
*/
type UserSettingsTable = { [key: string]: any }
export interface SettingsConfigProp<A> {
defaultValue?: A;
skipUrlEncoding?: boolean;
storageKey?: string;
type: Type<A>;
}
export interface SettingsConfig<T> {
applicableRoutespace?: string;
settings: { [K in keyof T]: SettingsConfigProp<T[K]> };
storagePath: string;
}
type UserSettingsContext = {
table: UserSettingsTable;
update: (key: string, value: any) => void
}
const UserSettings = createContext<UserSettingsContext>({
table: {},
update: () => { },
});
const SettingsProvider = ({ children }: { children: ReactChildren }) => {
const [settingsTable, updateSettingsTable] = useState({});
const update = (key: string, value: any) => {
updateSettingsTable(prev => ({ ...prev, [key]: value }))
}
useEffect(() => {
// fetch initial settings
}, []);
return <UserSettings.Provider value={{
table: settingsTable,
update,
}}>{children}</UserSettings.Provider>
}
const useSettings = <T, >(config: SettingsConfig<T>) => {
const { table, update } = useContext(UserSettings);
const [ident, reRender] = useState({});
const navigate = useNavigate();
const settings = useMemo(() => table[config.storagePath], [ident]);
const updateSettings = (updates: Partial<T>) => {
const newSettings = { ...settings, ...updates };
update(config.storagePath, newSettings);
// updateDatabase <- fire and forget
navigate(/* new url here */ window.location.toString())
reRender({})
};
return { updateSettings, settings }
}
export { SettingsProvider, useSettings }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment