Kyle Sharp
Kyle Sharp

Reputation: 177

Using a React hook in separate file to the component

I am wanting to create a data file for my project instead of having everything in the one file, however I am using React hooks to load in images. This becomes a problem when I want to have everything in separate files. The code gives me the 'Invalid hook call' message which I understand why it is wrong, but can't figure out how to get it to work for me.

EventData.js

import React from "react"
import Image from "gatsby-image"
import { graphql, useStaticQuery } from "gatsby"

const getImages = graphql`
  {
    btu: file(relativePath: { eq: "eventImage/btu.jpeg" }) {
      childImageSharp {
        fixed(height: 120, width: 500) {
          ...GatsbyImageSharpFixed_withWebp_tracedSVG
        }
      }
    }
  }
`

const data = useStaticQuery(getImages)
export const details = [
  {
    id: 1,
    img: <Image fixed={data.btu.childImageSharp.fixed} />,
    date: "2 Oct 2020",
    distance: "30km - 160km",
    name: "Brisbane Trail Ultra",
    location: "Brisbane, QLD",
  },
]

EventCalendar.js

const EventCalendar = () => {
  return (
    <Layout>
      <section>
        {details.map(details => {
          return <EventCard key={details.id} {...details}></EventCard>
        })}
      </section>
    </Layout>
  )
}

Upvotes: 2

Views: 10756

Answers (2)

Peter Lehnhardt
Peter Lehnhardt

Reputation: 4985

You have to define a custom hook, which looks something like this in your case:

import React from "react"
import Image from "gatsby-image"
import { graphql, useStaticQuery } from "gatsby"

const getImages = graphql`
  {
    btu: file(relativePath: { eq: "eventImage/btu.jpeg" }) {
      childImageSharp {
        fixed(height: 120, width: 500) {
          ...GatsbyImageSharpFixed_withWebp_tracedSVG
        }
      }
    }
  }
  `;

export function useDetails() {    
  const data = useStaticQuery(getImages);

  return [
    {
      id: 1,
      img: <Image fixed={data.btu.childImageSharp.fixed} />,
      date: "2 Oct 2020",
      distance: "30km - 160km",
      name: "Brisbane Trail Ultra",
      location: "Brisbane, QLD",
    },
  ];
}

To define custom hooks, define a function, which returns your desired values. In this function you can all hooks available from the react API.

Then in your main file write

const EventCalendar = () => {
  const details = useDetails();

  return (
    <Layout>
      <section>
        {details.map(detail => {
          return <EventCard key={details.id} {...detail}></EventCard>
        })}
      </section>
    </Layout>
  )
}

Upvotes: 2

Anhdevit
Anhdevit

Reputation: 2104

Only Call Hooks from React Functions Don’t call Hooks from regular JavaScript functions. Instead, you can:

✅ Call Hooks from React function components.

✅ Call Hooks from custom Hooks (we’ll learn about them on the next page). Another thing: Inside the map, you should change details to detail because is an item

const EventCalendar = () => {
  return (
    <Layout>
      <section>
        {details.map(detail => {
          return <EventCard key={details.id} {...detail}></EventCard>
        })}
      </section>
    </Layout>
  )
}

You can read about hook is here: https://reactjs.org/docs/hooks-rules.html

My suggestion is you can wrap it into component like that:

const ImageHook = () => {
  const data = useStaticQuery(getImages)
  return <Image fixed={data.btu.childImageSharp.fixed}/>
}

export const details = [
  {
    id: 1,
    img:  <ImageHook />,
    date: "2 Oct 2020",
    distance: "30km - 160km",
    name: "Brisbane Trail Ultra",
    location: "Brisbane, QLD",
  },
]

Upvotes: 0

Related Questions