Use React Context with Typescript successfully

The mission of this entry is to learn how to use React.Context using Typescript. Then we will create our context as next:

import {createContext} from 'react'
 
export const TasksContext = createContext()
 

At this point createContext we will need a default value so we are going to type what createContext is going to receive, in this case the Context Task will keep a property tasks:

import {createContext} from 'react'
 
type Task = {
    id: number;
    title: string;
    description: string;
}
 
type TasksContextType = {
    tasks: Task[]
} | undefined;
 
export const TasksContext = createContext<KanbanContextType>()
 

Now we need to build the Provider for this Context

 
type TaskContextProvider = {
    children: React.ReactNode;
}
 
function TaskContextProvider(props: TaskContextProvider){
    return <TaskContext.Provider value={{}}>
        {children}
    </TaskContext.Provider>
}
 
export {TaskContextProvider}
 

This TaskContextProvider will wrap the App Component. And the state and the methods to update this state will be managed by this Provider, for example:

 
type TaskContextProvider = {
    children: React.ReactNode;
}
 
function TaskContextProvider(props: TaskContextProvider){
    const [tasks, setTasks] = useState<Task[]>()
 
    const addTask = (task: Task) => {
        setTasks(...tasks, task)
    }
 
    return <TaskContext.Provider value={{tasks, addTask}}>
        {children}
    </TaskContext.Provider>
}

In this Provider we need to type the addTask in TasksContextType type

import {createContext} from 'react'
 
type Task = {
    id: number;
    title: string;
    description: string;
}
 
type TasksContextType = {
    tasks: Task[]
    addTask: (task: Task) => void
} | undefined;
 
const TasksContext = createContext<KanbanContextType>()
 

Now we need to create a hook for consuming our provided, if you use vite you should have this function in a separate file: hooks/useTasksContext

import {useContext} from 'react'
import {TasksContext} from '@/context/tasks-context.tsx 
 
function useTasksProvider(){
    const context = useContext(TasksContext)
    if(context===undefined){
        throw new Error('useTasksProvider should be used inside TasksContextProvider')
    }
    return context;
}
 

At this point we have a Component to provide the TaskContext and a hook for consuming it. Now we just need to wrap our entire app with the consumer:

import {TasksContextProvider} from '@/context/tasks-context';
export default function App(){
    return <TasksContextProvider>
        {/* YOUR APP /*}
    </TasksContextProvider>
}
 

And now you just have to consume your context with the hooks created

import {useTasksContext} from '@hooks/useTasksContext'
 
export default tfunction MyComponent(){
    const {tasks, addTask} = useTasksContext()
    
    // use as you want it
}
 

That’s all guys !

Happy Hacking !