sajad torkamani

See full working example here.

Create an interface/type to describe the shape of your context:

import { createContext } from 'react';

export interface CounterContextType {
  counter: number;
  increment: () => void;
  decrement: () => void;
}

export const CounterContext = createContext<CounterContextType | null>(null);

Create a provider component:

import { useState } from 'react'
import { CounterContext, CounterContextType } from '../contexts/CounterContext'

export const CounterProvider: React.FC<{ children: React.ReactNode }> = ({
  children,
}) => {
  const [counter, setCounter] = useState(0)

  const context: CounterContextType = {
    counter,
    increment: () => setCounter((prevValue) => prevValue + 1),
    decrement: () => setCounter((prevValue) => prevValue - 1),
  }

  return (
    <CounterContext.Provider value={context}>
      {children}
    </CounterContext.Provider>
  )
}

Create a hook that lets you use the context:

import { useContext } from 'react';
import { CounterContext } from '../contexts/CounterContext';

export function useCounter() {
  const counter = useContext(CounterContext);

  if (!counter) {
    throw new Error(
      'useCounter has to be used within <CounterContext.Provider>'
    );
  }

  return counter;
}

Consume the context via your hook:

import './App.css'
import { useCounter } from './hooks/useCounter'

function App() {
  const { counter, increment, decrement } = useCounter()

  return (
    <>
      <div>Clicks: {counter}</div>

      <div style={{ display: 'flex', gap: '10px', marginTop: '15px' }}>
        <button onClick={increment}>Increment</button>
        <button onClick={decrement}>Decrement</button>
      </div>
    </>
  )
}

export default App