Skip to content

Instantly share code, notes, and snippets.

@gilbarbara
Last active February 19, 2025 17:02
Show Gist options
  • Save gilbarbara/07544eb56cc5f7a294b5104eddad47f5 to your computer and use it in GitHub Desktop.
Save gilbarbara/07544eb56cc5f7a294b5104eddad47f5 to your computer and use it in GitHub Desktop.
React Context with hook
import { createContext, ReactNode, useContext, useMemo, useState } from 'react';
const appState = { darkMode: true, locale: 'en' } as const;
export interface AppState {
darkMode: boolean;
locale: 'en' | 'pt';
}
export const OptionsContext = createContext<{
options: AppState;
setOptions: (update: Partial<AppState> | ((previous: AppState) => Partial<AppState>)) => void;
}>({
options: appState,
setOptions: () => {},
});
OptionsContext.displayName = 'OptionsContext';
export function OptionsProvider(props: { children: ReactNode }) {
const [options, setOptions] = useState<AppState>(appState);
const customSetOptions = (
update: Partial<AppState> | ((previous: AppState) => Partial<AppState>),
) => {
setOptions(previous =>
typeof update === 'function'
? { ...previous, ...update(previous) }
: { ...previous, ...update },
);
};
const value = useMemo(() => ({ options, setOptions: customSetOptions }), [options]);
return <OptionsContext.Provider value={value} {...props} />;
}
export function useOptions(): {
options: AppState;
setOptions: (update: Partial<AppState> | ((previous: AppState) => Partial<AppState>)) => void;
} {
const context = useContext(OptionsContext);
if (!context) {
throw new Error('useOptions must be used within a OptionsProvider');
}
return context;
}
// Example usage:
/*
function DarkModeToggle() {
const { options, setOptions } = useOptions();
return (
<div>
<p>Dark Mode: {options.darkMode ? 'On' : 'Off'}</p>
<button onClick={() => setOptions(previous => ({ darkMode: !previous.darkMode }))}>
Toggle Dark Mode
</button>
</div>
);
}
export default function App() {
return (
<OptionsProvider> <- This is needed to provide the context to the children
<DarkModeToggle />
</OptionsProvider>
);
}
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment