Create an Avatar Component in Gatsby with TypeScript: Part 2 – Gatsby Image
Tags: react, gatsby, typescript, graphql
Published: 2020-01-08 04:26:13

---
title: Create an Avatar Component in Gatsby with TypeScript: Part 2 – Gatsby Image
published: true
date: 2020-01-07 00:00:00 UTC
tags: react, gatsby, typescript, graphql
canonical_url: https://joelmturner.com/blog/avatar-component-gatsby-2
cover_image: https://joelmturner.com/static/bce620db9bdf5e8b532fd137f3f5bd3c/cefe4/gatsby-avatar-02.webp
series: Create an Avatar Component in Gatsby with TypeScript
---

In [Part 1](https://dev.to/joelmturner/create-an-avatar-component-in-gatsby-with-typescript-part-1-17he) we put together a simple avatar component that can receive an image URL and render it out as around image.

To get the full benefit of Gatsby Image we need to make sure our image is pulled into our graphql. We'll need to install a couple of plugins to help us here. [`gatsby-image`](https://www.gatsbyjs.org/packages/gatsby-image), [`gatsby-transformer-sharp`](https://www.gatsbyjs.org/packages/gatsby-transformer-sharp), [`gatsby-plugin-sharp`](https://www.gatsbyjs.org/packages/gatsby-plugin-sharp) will be needed.

Let's install `gatsby-image`
```bash
npm install --save gatsby-image
```

Then, if you don't already have `gatsby-transformer-sharp` and `gatsby-plugin-sharp` we can install them.
```bash
npm install --save gatsby-transformer-sharp gatsby-plugin-sharp
```

Then in your gatsby-config.js:
```js
plugins: [`gatsby-transformer-sharp`, `gatsby-plugin-sharp`]
```

We'll need a source plugin set up as well. For this example, we're going to use `gatsby-source-filesystem`. Here is what our `gatsby-config` might look like, assuming our images are in `src/assets`.

```js
const path = require(`path`)

module.exports = {
  plugins: [
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `assets`,
        path: path.join(__dirname, `src`, `assets`),
      },
    },
    `gatsby-plugin-sharp`,
    `gatsby-transformer-sharp`,
  ],
}
```

Now let's drop our image file into our assets folder and create a query for it. We can use the hook for StaticQuery in our component which will make the image available through the data prop. Since we know the size of the image we can add those dimensions in our graphql query so the browser doesn't have to do all the work.

```jsx
  const data = useStaticQuery(graphql`
    query {
      placeholderImage: file(relativePath: { eq: "monster-01-headshot.png" }) {
        childImageSharp {
          fixed(width: 75, height: 75) {
            ...GatsbyImageSharpFixed
          }
        }
      }
    }
  `)
```
Then we need to add the `Img` component from `gatsby-image` so that it can do its magic.

```jsx
import Img from "gatsby-image"

function Avatar(props) {
  {...}
  return (
    <Img
      style={styles}
      fixed={data.placeholderImage.childImageSharp.fixed}
      alt={altText}
      title={title} />
  )
}
```
Now let's put it all together.

```jsx
import React from "react"
import { useStaticQuery, graphql } from "gatsby"
import Img from "gatsby-image"

function Avatar(props) {
  const data = useStaticQuery(graphql`
    query {
      placeholderImage: file(relativePath: { eq: "monster-01-headshot.png" }) {
        childImageSharp {
          fixed(width: 75, height: 75) {
            ...GatsbyImageSharpFixed
          }
        }
      }
    }
  `)

  const {url, altText, title} = props;
  const styles = {
    width: '75px',
    height: '75px',
    borderRadius: '50%'
  }

  return (
    <Img
      style={styles}
      fixed={data.placeholderImage.childImageSharp.fixed}
      alt={altText}
      title={title} />
  )
}

export default Avatar
```

We're still missing the ability to pass a URL to our avatar component so let's add that back in. We can return a regular `img` element if we get a URL. Using `fixed` will be better since we're not worried about fluid mode with this component.

```jsx
import React from "react"
import { useStaticQuery, graphql } from "gatsby"
import Img from "gatsby-image"

function Avatar(props) {
  const data = useStaticQuery(graphql`
    query {
      placeholderImage: file(relativePath: { eq: "monster-01-headshot.png" }) {
        childImageSharp {
          fixed(width: 75, height: 75) {
            ...GatsbyImageSharpFixed
          }
        }
      }
    }
  `)

  const {url, altText, title} = props;
  const styles = {
    width: '75px',
    height: '75px',
    borderRadius: '50%'
  }

  if (url) {
    return (
      <img
        style={styles}
        src={url}
        alt={altText}
        title={title} />
    );
  }

  return (
    <Img
      style={styles}
      fixed={data.placeholderImage.childImageSharp.fixed}
      alt={altText}
      title={title} />
  )
}

export default Avatar
```

This allows us to call avatar without us needing to pass a prop of the image URL. If you need multiple avatar images for your team you can add them to the quite and pass a user prop down and we'll grab that from the query. We can name the queries to match the users like so:

```jsx
function Avatar(props) {
  const data = useStaticQuery(graphql`
      query {
        monster1: file(relativePath: { eq: "monster-01-headshot.png" }) {
          childImageSharp {
            fixed(width: 75, height: 75) {
              ...GatsbyImageSharpFixed
            }
          }
        }
        monster2: file(relativePath: { eq: "monster-02-headshot.png" }) {
          childImageSharp {
            fixed(width: 75, height: 75) {
              ...GatsbyImageSharpFixed
            }
          }
        }
      }
    `)

  const {url, altText, title, user} = props;
  const image = data[user].childImageSharp.fixed;
  {...}
```

That way we can pass `monster1` or `monster2` in our `user` prop to have it render that monster.


```jsx
<Avatar
    alText='Monster P. Whittington portrait'
    title='Monster P. Whittington'
    user='monster1' />
```

```jsx
<Avatar
    alText='Mons T. Cobblepot portrait'
    title='Mons T. Cobblepot'
    user='monster2' />
```

Nice, now we can type it so it's easier to know what name can be used and to see if our structure is correct if we ever need to edit it.