Building reusable react hooks with generics
In my previous post, I showed a simple react hook that makes a specific api call. This time, I want to show how to turn that specific hook into a better, more reusable version.
Im going to use a very powerful feature of typescript called generics.
To start off, let's see our first iteration of the api hook again.
This hook works okay, but if we wanted to make a similar api call to another endpoint, we would have to create another hook that would repeat most of what we have.
A more generic version of this hook could like this:
Lets compare whats happening on line 5 with our previous example
Original:
export default (): [(id: string) => void, User, string] => {
Updated:
export default <T>(): [(url: string) => void, string, T?] => {
First, I have replaced the id with a url so we can any service needed.
Second, I replaced the User type with a typescript generic. A generic allows us to call the same function with different types. I moved the response variable to the end because it can possibly be undefined.
Next, I replaced any other reference to User with the generic keyword
const [response, setResponse] = useState<T>();
const res = await getResource<T>(`${path}/${id}`);
This will ensure that the data I get back from the api will be recognized as the type I pass into T when I call the function from within my application.
Finally I add the path variable to the getResponseTest function:
const getResponseTest = async (url: string) => {
try {
const res = await getResource<T>(url);
Now we can call this hook in our application with any type and path we need.
Line 12 useTest<User>
is where we specify the type we want our generic to become.
If we had another part of the application where we get something like an invoice, we can use the same hook, just swap out the type, url and update the UI.