Using Generics in Hooks
Generics are a powerful feature in TypeScript that let you write flexible, reusable code while still maintaining type safety. When building custom hooks in React, generics allow you to create hooks that can adapt to different data types without losing the benefits of static type checking. This is especially useful for hooks that fetch data, handle forms, or manage any logic that could work with multiple types.
Suppose you want to build a custom hook for fetching data from an API. If you hard-code the type of data it returns, you limit the hook's usefulness. Instead, you can use a generic type parameter so the hook can work with any data shape, and TypeScript will enforce correct usage.
For example, a generic data fetching hook might look like this:
import { useState, useEffect } from "react";
function useFetch<T>(url: string) {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
setLoading(true);
fetch(url)
.then((res) => res.json())
.then((json: T) => {
setData(json);
setLoading(false);
});
}, [url]);
return { data, loading };
}
Here, the <T> syntax is used to declare a generic type parameter. When you use this hook, you specify the type of data you expect, and TypeScript will make sure you use it correctly:
type User = {
id: number;
name: string;
};
const { data, loading } = useFetch<User>("/api/user/1");
This pattern ensures that data will always be of type User | null, so you get full type safety across your component.
Another common scenario is form handling. You can create a generic hook that manages form state for any shape of form values:
import { useState } from "react";
function useForm<T>(initialValues: T) {
const [values, setValues] = useState<T>(initialValues);
function handleChange<K extends keyof T>(key: K, value: T[K]) {
setValues((prev) => ({
...prev,
[key]: value,
}));
}
return { values, handleChange };
}
When using this hook, you define the shape of your form values up front:
type LoginForm = {
username: string;
password: string;
};
const { values, handleChange } = useForm<LoginForm>({
username: "",
password: "",
});
This approach gives you strong typing for form values and change handlers, reducing bugs and improving code clarity.
1. What is the benefit of using generics in custom hooks?
2. Which syntax is used to declare a generic type parameter in a hook?
Danke für Ihr Feedback!
Fragen Sie AI
Fragen Sie AI
Fragen Sie alles oder probieren Sie eine der vorgeschlagenen Fragen, um unser Gespräch zu beginnen
Awesome!
Completion rate improved to 4.17
Using Generics in Hooks
Swipe um das Menü anzuzeigen
Generics are a powerful feature in TypeScript that let you write flexible, reusable code while still maintaining type safety. When building custom hooks in React, generics allow you to create hooks that can adapt to different data types without losing the benefits of static type checking. This is especially useful for hooks that fetch data, handle forms, or manage any logic that could work with multiple types.
Suppose you want to build a custom hook for fetching data from an API. If you hard-code the type of data it returns, you limit the hook's usefulness. Instead, you can use a generic type parameter so the hook can work with any data shape, and TypeScript will enforce correct usage.
For example, a generic data fetching hook might look like this:
import { useState, useEffect } from "react";
function useFetch<T>(url: string) {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
setLoading(true);
fetch(url)
.then((res) => res.json())
.then((json: T) => {
setData(json);
setLoading(false);
});
}, [url]);
return { data, loading };
}
Here, the <T> syntax is used to declare a generic type parameter. When you use this hook, you specify the type of data you expect, and TypeScript will make sure you use it correctly:
type User = {
id: number;
name: string;
};
const { data, loading } = useFetch<User>("/api/user/1");
This pattern ensures that data will always be of type User | null, so you get full type safety across your component.
Another common scenario is form handling. You can create a generic hook that manages form state for any shape of form values:
import { useState } from "react";
function useForm<T>(initialValues: T) {
const [values, setValues] = useState<T>(initialValues);
function handleChange<K extends keyof T>(key: K, value: T[K]) {
setValues((prev) => ({
...prev,
[key]: value,
}));
}
return { values, handleChange };
}
When using this hook, you define the shape of your form values up front:
type LoginForm = {
username: string;
password: string;
};
const { values, handleChange } = useForm<LoginForm>({
username: "",
password: "",
});
This approach gives you strong typing for form values and change handlers, reducing bugs and improving code clarity.
1. What is the benefit of using generics in custom hooks?
2. Which syntax is used to declare a generic type parameter in a hook?
Danke für Ihr Feedback!