Skip to content

Instantly share code, notes, and snippets.

@cfogelklou
Last active May 12, 2023 07:21
Show Gist options
  • Save cfogelklou/6bcdc3656e16e37b296c082463402880 to your computer and use it in GitHub Desktop.
Save cfogelklou/6bcdc3656e16e37b296c082463402880 to your computer and use it in GitHub Desktop.
This is an example of managing application state using the React Context API and the useReducer hook in typescript.
/*
This is an example of managing application state using the React Context API
and the useReducer hook in typescript. It demonstrates a pattern commonly
used in React applications to provide global state management and share state
and actions across components. It is all implemented in a single file for easy
copy/paste.
- Author: Chris Fogelklou
- Tags: useContext, Provider, useReducer, createContext
Key points:
- Defining the shape of the application state: AppState
- Creating an initial state with default values and placeholder
functions in the initialState.
- Defining actions as string constants in the actions object.
- Implementing a reducer function, ActionToNewAppStateReducer,
to handle actions and update the state.
- Creating a global context, AppStateContext, using the createContext
function to share the application state.
- Using the useGlobalContext hook to access the application state
and actions from within components.
- Implementing a Provider component that manages the application
state using the useReducer hook and provides the state and
actions through the global context.
- By encapsulating the state and related actions within a provider
component, this approach enables components to access and modify
the shared state without the need for prop drilling.
It promotes code organization, reusability, and simplifies
state management in larger React applications.
*/
import React, {createContext, useContext} from 'react';
// Define the shape of the application state
export type AppState = {
userName: string;
setUserName: (name: string) => void;
reset: () => void;
};
// Initial state of the application
const initialState: AppState = {
userName: '', // set a default value
setUserName: (_name: string) => {},
reset: () => {},
};
// Actions
export const actions = {
SET_USERNAME: 'SET_USERNAME',
RESET: 'RESET',
};
// Interface for application state actions
export interface AppStateAction {
type: string;
SET_USERNAME?: string;
RESET?: undefined;
}
// Convert actions into a new state
export function ActionToNewAppStateReducer(
state: AppState,
action: AppStateAction,
) {
let newstate = state;
switch (action.type) {
case actions.SET_USERNAME:
if (!!action.SET_USERNAME) {
newstate = {...state, userName: action.SET_USERNAME};
}
break;
case actions.RESET:
newstate = {...state, ...initialState};
default:
break;
}
return newstate;
}
// Create a app context for the application state
export const AppStateContext = createContext<AppState>(initialState);
// Custom hook to access the global context
export const useGlobalContext = () => useContext(AppStateContext);
// Provider component that manages the application state
export function Provider(p: React.PropsWithChildren<{}>) {
const [state, dispatch] = React.useReducer(
ActionToNewAppStateReducer,
initialState,
);
// Create an appState object with the necessary functions to update the state
const appState: AppState = {
userName: state.userName,
setUserName: (name: string) => {
dispatch({type: actions.SET_USERNAME, SET_USERNAME: name});
},
reset: () => {
dispatch({type: actions.RESET});
},
};
return (
<AppStateContext.Provider value={appState}>
{p.children}
</AppStateContext.Provider>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment