How can I use a field as a filter from one graphql query to get a fluid image thats in a separate query?

Viewed 226

I have two graphql sources, one for fluid images and one for characters in a mongo database. I'm mapping the characters to the page and I need to use the character names (the name field in the "allMongodbMobileLegendsdevChamps") as a filter (using originalName filter possibly) to find the fluid img. So I have something like this

query MyQuery {
  allMongodbMobileLegendsdevChamps {
    nodes {
      name
    }
  }
  allImageSharp(filter: {fluid: {originalName: {eq: "characterName.jpg"}}}) {
    nodes {
      fluid {
        ...allImageSharpFluid
      }
    }
  }
}

const Index = ({ data }) => {
  const {
    allMongodbMobileLegendsdevChamps: { nodes: champs },
    allImageSharp: { nodes: fluid },
  } = data
  return (
    <section className={grid}>
      {champs.map(champ => {
        return (
          <Link to={`/champ/${champ.name}`}>
            <Image fluid={fluid.fluid} />
            <h3>{champ.name}</h3>
          </Link>
        )
      })}
    </section>
  )
}

If I wasnt using graphql, I'd just set the src in image to "champ.name" like this:

<Image src = `/path/to/img/${champ.name}.jpg` />

How can I filter my image query with the champ.name? Should I use Apollo for something like this?

2 Answers

This is Gatsby and currently it is not possible because you can’t pass in variables to queries follow this GH issue https://github.com/gatsbyjs/gatsby/issues/10482

Supposing that passing variables was possible, I would make all characters as a page query that will allow me to restructure the name from props and then a static query to which I would pass in the name as filter.

I used this solution and adapted it slightly for my needs: Variables in graphQL queries

In a parent component I map all the champions and create a child component for each one, and pass it the champions name.

In the child component, I have a variable, name, that stores the correct node for the image I want to display by using the find method to match the champions name to the images relativePath (the images have the same exact name as the champion). I then call the function renderImage which consumes the variable "name" and finds the fluid image in node.childImageSharp.fluid, and creates my image component with the correct fluid image location.

import React from "react"
import { useStaticQuery, graphql } from "gatsby"
import { displayName } from "../../utils/championName"
import * as S from "../styled/ChampionGridCard"

const renderImage = file => {
  return <S.ChampionImage fluid={file.node.childImageSharp.fluid} />
}

const ChampionGridCard = props => {
  const data = useStaticQuery(graphql`
    {
      allFile(filter: { sourceInstanceName: { eq: "champImages" } }) {
        edges {
          node {
            extension
            relativePath
            childImageSharp {
              fluid {
                ...GatsbyImageSharpFluid
              }
            }
          }
        }
      }
    }
  `)

  const name = data.allFile.edges.find(
    image => image.node.relativePath === `ssbu/${props.champName}.jpg`
  )

  return (
    <S.ChampionGridCard to={`/champ/${props.champName}`}>
      <S.ChampionImageWrapper>{renderImage(name)}</S.ChampionImageWrapper>
    </S.ChampionGridCard>
  )
}

export default ChampionGridCard

Related