We couple useState and useContext to estalish the native way of managing the global state, that is available everywhere for any components to use.

1import {
2    useState, // for state creation
3    createContext, useContext, // for context
4    Dispatch, SetStateAction, // for setter function
5} from "react"

Declaring Type, Context, and Hook

Declare a type for the state, which consists of a setter and a getter

1// define the type for the context
2type MyContextType = {
3    state: string
4    dispatch: Dispatch<SetStateAction<string>>
5}

Create a custome context with that type using createContext

1// define the context type
2const MyContext = createContext<
3    MyContextType | null
4>(null) // null when initialized

Create a custome hook for handling errors and return the context

1// define a custom hook for getting the data
2const useMyContext = () => {
3    const context = useContext(MyContext)
4    // edge case where the parent component 
5    // doesn't pass the state to the children
6    if (!context) {
7        return null
8    }
9    return context;
10};

In the Parent Component

In the parent component (that), we need to first create a initial state using useState with an initialized value.

1const initString: string = "I'm an initial state"
2const [data, setData] = useState<string>(initString);

We then need to wrap the children components with a context provider, which we need to extract them from the MyContext we declared before. We need pass the getter and setter value as a value arg with the context provider.

1<MyContext.Provider
2    value={{
3        state: data,
4        dispatch: setData
5    }}
6>
7    <UseContextChildComponent />
8</MyContext.Provider>
Parent ComponentI'm an initial state

In the Children Components

In the children components, we need to extract the context from useMyContext– and must check if the context is provided by parent or not.

1const context = useMyContext()
2if (!context)
3    return (
4        <p>Context is not provided</p>
5    )

If the context exists, then we can safely call the context and extract the value as well as a dispatch function to set the state from that child component.

I am a Child Component
1function UseContextChildComponent() {
2    const context = useMyContext()
3    if (!context)
4        return (
5        <p>Context is not provided</p>
6    )
7
8    const { dispatch } = context
9    return (
10        <div>
11            <span>Child Component</span>
12            <Button
13                onClick={() => 
14                    dispatch(
15                        "hello from children component!"
16            )}>
17                Set State from Child
18            </Button>
19        </div>
20    );
21}