Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Oppiskele Typing Context API | Advanced React Patterns with TypeScript
TypeScript Essentials for React

bookTyping Context API

When you need to share state across many components in a React application, the Context API is a powerful tool. TypeScript helps you make this state sharing safer and more predictable by allowing you to explicitly type the context's value and provider. You will see how to define a typed context step by step, and how to handle default values and consumers with TypeScript.

Start by defining the shape of the data you want to share. For instance, imagine you want to share user authentication information. First, define an interface for the context value:

interface AuthContextType {
  user: string | null;
  login: (username: string) => void;
  logout: () => void;
}

Next, create the context itself. Since the initial value is required, you can use null or a partial object, but you must reflect this in the type definition. The preferred way is to allow null in the type, making it clear to consumers that the context might not be available:

import React, { createContext, useContext, useState, ReactNode } from "react";

const AuthContext = createContext<AuthContextType | null>(null);

Now, implement the provider component. This component will hold the state and provide the context value to its children:

type AuthProviderProps = {
  children: ReactNode;
};

export function AuthProvider({ children }: AuthProviderProps) {
  const [user, setUser] = useState<string | null>(null);

  const login = (username: string) => setUser(username);
  const logout = () => setUser(null);

  const value: AuthContextType = { user, login, logout };

  return (
    <AuthContext.Provider value={value}>
      {children}
    </AuthContext.Provider>
  );
}

To consume this context safely, you should create a custom hook. This hook will use useContext and throw an error if the context is not available, ensuring that your components are always wrapped in the provider:

export function useAuth() {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error("useAuth must be used within an AuthProvider");
  }
  return context;
}

Typing the context value and provider in this way ensures that all consumers of the context receive the correct value shape, and that your app will catch any misuse at compile time. This approach also makes it clear when a context can be null, encouraging you to handle such cases in your components.

Default values in createContext can be tricky. If you provide a default object, consumers outside a provider will not fail, but may receive incorrect or incomplete data. By using null and allowing AuthContextType | null, you enforce that all consumers must be inside a provider or handle the null case. This pattern leads to safer and more maintainable code.

When using TypeScript with React Context, always define the value's type explicitly. If the context value can be null, include null in the type. Use custom hooks to simplify consumption and add runtime checks. This keeps your state sharing reliable and your codebase robust.

1. Why is it important to type the value provided by a React Context?

2. What should you do when a context value can be null?

question mark

Why is it important to type the value provided by a React Context?

Select the correct answer

question mark

What should you do when a context value can be null?

Select the correct answer

Oliko kaikki selvää?

Miten voimme parantaa sitä?

Kiitos palautteestasi!

Osio 6. Luku 1

Kysy tekoälyä

expand

Kysy tekoälyä

ChatGPT

Kysy mitä tahansa tai kokeile jotakin ehdotetuista kysymyksistä aloittaaksesi keskustelumme

Awesome!

Completion rate improved to 4.17

bookTyping Context API

Pyyhkäise näyttääksesi valikon

When you need to share state across many components in a React application, the Context API is a powerful tool. TypeScript helps you make this state sharing safer and more predictable by allowing you to explicitly type the context's value and provider. You will see how to define a typed context step by step, and how to handle default values and consumers with TypeScript.

Start by defining the shape of the data you want to share. For instance, imagine you want to share user authentication information. First, define an interface for the context value:

interface AuthContextType {
  user: string | null;
  login: (username: string) => void;
  logout: () => void;
}

Next, create the context itself. Since the initial value is required, you can use null or a partial object, but you must reflect this in the type definition. The preferred way is to allow null in the type, making it clear to consumers that the context might not be available:

import React, { createContext, useContext, useState, ReactNode } from "react";

const AuthContext = createContext<AuthContextType | null>(null);

Now, implement the provider component. This component will hold the state and provide the context value to its children:

type AuthProviderProps = {
  children: ReactNode;
};

export function AuthProvider({ children }: AuthProviderProps) {
  const [user, setUser] = useState<string | null>(null);

  const login = (username: string) => setUser(username);
  const logout = () => setUser(null);

  const value: AuthContextType = { user, login, logout };

  return (
    <AuthContext.Provider value={value}>
      {children}
    </AuthContext.Provider>
  );
}

To consume this context safely, you should create a custom hook. This hook will use useContext and throw an error if the context is not available, ensuring that your components are always wrapped in the provider:

export function useAuth() {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error("useAuth must be used within an AuthProvider");
  }
  return context;
}

Typing the context value and provider in this way ensures that all consumers of the context receive the correct value shape, and that your app will catch any misuse at compile time. This approach also makes it clear when a context can be null, encouraging you to handle such cases in your components.

Default values in createContext can be tricky. If you provide a default object, consumers outside a provider will not fail, but may receive incorrect or incomplete data. By using null and allowing AuthContextType | null, you enforce that all consumers must be inside a provider or handle the null case. This pattern leads to safer and more maintainable code.

When using TypeScript with React Context, always define the value's type explicitly. If the context value can be null, include null in the type. Use custom hooks to simplify consumption and add runtime checks. This keeps your state sharing reliable and your codebase robust.

1. Why is it important to type the value provided by a React Context?

2. What should you do when a context value can be null?

question mark

Why is it important to type the value provided by a React Context?

Select the correct answer

question mark

What should you do when a context value can be null?

Select the correct answer

Oliko kaikki selvää?

Miten voimme parantaa sitä?

Kiitos palautteestasi!

Osio 6. Luku 1
some-alt