Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
import React from 'react';
enum Actions {
LIGHT = 'light',
DARK = 'dark',
BROWN = 'brown',
}
interface ThemeProps {
color: string;
backgroundColor: string;
}
interface Theme {
theme: ThemeProps;
}
const themes = {
light: {
color: '#504b4b',
backgroundColor: '#ffffff',
},
dark: {
color: '#ffffff',
backgroundColor: '#504b4b',
},
brown: {
color: '#ffffff',
backgroundColor: '#795548',
},
};
type Action = { type: Actions.LIGHT } | { type: Actions.DARK } | { type: Actions.BROWN };
type Dispatch = (action: Action) => void;
type State = { theme: ThemeProps };
const ThemeStateContext = React.createContext<State | undefined>(undefined);
const ThemeDispatchContext = React.createContext<Dispatch | undefined>(undefined);
function themeReducer(state: State, action: Action) {
switch (action.type) {
case Actions.LIGHT: {
return { ...state, theme: themes.light };
}
case Actions.DARK: {
return { ...state, theme: themes.dark };
}
case Actions.BROWN: {
return { ...state, theme: themes.brown };
}
default: {
throw new Error(`Unhandled action type: `);
}
}
}
function ThemeProvider({ children }: any) {
const [state, dispatch] = React.useReducer(themeReducer, { theme: themes.brown });
return (
<ThemeStateContext.Provider value={state}>
<ThemeDispatchContext.Provider value={dispatch}>{children}</ThemeDispatchContext.Provider>
</ThemeStateContext.Provider>
);
}
function useThemeState() {
const context = React.useContext(ThemeStateContext);
if (context === undefined) {
throw new Error('useCountState must be used within a CountProvider');
}
return context;
}
function useThemeDispatch() {
const context = React.useContext(ThemeDispatchContext);
if (context === undefined) {
throw new Error('useCountDispatch must be used within a CountProvider');
}
return context;
}
export { ThemeProvider, useThemeState, useThemeDispatch, Theme, Actions };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment