How to integrate Gravatar with custom fallback on React App and tanstack query
Tags: gravatar, tanstackquery, react, tanstack
Published: 2024-05-15 11:01:32

Recently at work I integrated the famous service to manage avatar: **Gravatar**
This service is very useful, because with only one configuration we can have the same avatar in different places.

So, let's go into the deep for integrating Gravatar on React application using **tanstack query**.

Prerequisites:
- React 
- Tanstack query
- Valibot

First of all, we analyze how to get avatar image from Gravatar. Here the official doc:
https://docs.gravatar.com/api/avatars/images/

We have a lot of configurations, but for us are importants 3 things:

- Email Hash (MD5 or SHA256)
- Default parameter
- Json format 

## Email Hash
With this we can get the avatar image. Just call this url with email hashed

For example: 

```
https://gravatar.com/avatar/27205e5c51cb03f862138b22bcb5dc20f94a342e744ff6df1b8dc8af3c865109
```

So we know that if we call this url we obtain the avatar. Cool.😎

But, if I don't have any account on Gravatar, how can manage this situation?

Let's see the default parameter

## Default parameter
Gravatar offer differents parameters for our url. One of this is `d=404`

`d` means default and `404` is the famous error. So if we don't have any account on Gravatar the url will response with `Not found`.
So the url will be something like that:

```
https://gravatar.com/avatar/27205e5c51cb03f862138b22bcb5dc20f94a342e744ff6df1b8dc8af3c865109?d=404
```

## Json format
If we want more information on this Gravatar account we can add the json extension on url. For example in my case I added this:

```
https://gravatar.com/avatar/27205e5c51cb03f862138b22bcb5dc20f94a342e744ff6df1b8dc8af3c865109.json?d=404
```

This will return an specific json structure with also the avatar url.
More info here: https://docs.gravatar.com/api/profiles/json/

## Code
Let's look the code


Create schema validation with Valibot

```ts
import { array, object, string, type Output } from "valibot";

export const GravatarSchema = object({
  entry: array(
    object({
      photos: array(
        object({
          value: string(),
        })
      ),
    })
  ),
});

export type GravatarSchema = Output<typeof GravatarSchema>;
```

Make the api call with Tanstack Query

```ts
import { GravatarSchema } from '@/types';
import { gravatarClient } from '@/utils';

export const getAvatar = async (emailHash: string) =>
	gravatarClient.get(`/${emailHash}.json?d=404`, GravatarSchema);

```

Here we can use the [md5 library](https://www.npmjs.com/package/md5) to generate email hash or [sha256](https://www.npmjs.com/package/sha256) if we want be safe.

```ts
const { data, isError } = useQuery({
		queryKey: ['getAvatar', username],
		queryFn: () => getAvatar(md5(username))
	});
```

Check if we have an error and we show the fallback icon or we show the avatar.

```tsx
<div className="mr-4">
  <Avatar>
    {!isError ? (
      <AvatarImage
        className="rounded-b-lg"
        src={data?.entry
          .flatMap((item) => item.photos.map((photo) => photo.value))
          .at(0)}
        alt={username}
      />
    ) : (
      <AvatarImage className="bg-gray p-1" src={UserIcon} alt="avatar-fallback" />
    )}
  </Avatar>
</div>
```

And that's it.

See you next time. ✨