Last active
May 12, 2023 07:21
-
-
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 file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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