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?
Tak for dine kommentarer!
Spørg AI
Spørg AI
Spørg om hvad som helst eller prøv et af de foreslåede spørgsmål for at starte vores chat
Awesome!
Completion rate improved to 4.17
Using Generics in Hooks
Stryg for at vise menuen
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?
Tak for dine kommentarer!