A quick example of React Context API with Typescript that can be adapted for different use cases. This example is based on storing an array of todos (which are stored as strings), and providing a function to add a new todo. But this can be replaced with anything (and renamed to anything).
Types
I like to start with defining the type definitions. In this case we have the todos, which are stored as a string array, and a function that adds a new todo:
types.ts
export type TodosContextState = {
todos: string[];
addTodo: (name: string) => void;
};
Context Provider
Next we use this type to create a provider component that stores the state that we want to make available to other components using context.
TodosProvider.tsx
import React, { createContext, useState, FC } from "react";
import { TodosContextState } from "./types";
const contextDefaultValues: TodosContextState = {
todos: [],
addTodo: () => {}
};
export const TodosContext = createContext<TodosContextState>(
contextDefaultValues
);
const TodosProvider: FC = ({ children }) => {
const [todos, setTodos] = useState<string[]>(contextDefaultValues.todos);
const addTodo = (newTodo: string) => setTodos((todos) => [...todos, newTodo]);
return (
<TodosContext.Provider
value={{
todos,
addTodo
}}
>
{children}
</TodosContext.Provider>
);
};
export default TodosProvider;
We set the default values for our context with contextDefaultValues
. For functions we can just set them as () => {}
to make typescript happy before they are set when we create the provider.
TodosProvider Module
I like to make my React components modules, so here is the index.ts for the TodosProvider
module.
index.ts
export { TodosContext, default } from "./TodosContext";
Consuming Context
Here is an example of using the todos context. It is as simple as:
const { todos } = useContext(TodosContext);
Using this in a component would look something like this:
Todos.tsx
import React, { useContext } from "react";
import TodosProvider, { TodosContext } from "./TodosContext";
const Todos = () => {
const { todos, addTodo } = useContext(TodosContext);
return (
<div>
<div>
{todos.map((todo, i) => (
<div key={i}>{todo}</div>
))}
</div>
<button onClick={() => addTodo("new todo")}>add todo</button>
</div>
);
};
export default () => (
<TodosProvider>
<Todos />
</TodosProvider>
);
NOTE: By wrapping the Todos
component with the TodosProvider
component
export default () => (
<TodosProvider>
<Todos />
</TodosProvider>
);
This context will not be available to any other components (except for child components). If you would like this context to be shared between multiple components move it up the component tree so it covers all components that need to use it. It can even wrap the whole application.
Full example
Here's the example in full on codesandbox:
Top comments (9)
Great post! :)
thanks help me lot
This helped me a lot thank you!
Thank you, this was really helpfull. Good job!!
Thanks for sharing your knowledge with us. This blog post helped me comprehend more about how to use React Context API with NextJS and Typescript. Keep it up brother.
Great article, Alexander. This really helped me out. Thanks for sharing!
hero without cloak!
thanks help me a lot
Thanks bro! It helped me a lot... :D
Great example!