简体   繁体   中英

React, gatsbyjs: Looping through object - Component doesn't get rendered

I have the following component in a Gatsbyjs project:

styleItem.js

import React from 'react'
import styled from 'styled-components'
import BackgroundImage from 'gatsby-background-image'
import {StaticQuery, graphql } from "gatsby"
import {Col } from 'react-bootstrap'

import '../styles/styles.css'

const StyleItem = (props) => {
    return (
        <StaticQuery 
            query={graphql`
                query {
                    street: file(relativePath: { eq: "2.jpg" }) {
                        childImageSharp {
                        fluid(quality: 90, maxWidth: 1920) {
                            ...GatsbyImageSharpFluid_withWebp
                            }
                        }
                    }
                    casual: file(relativePath: { eq: "3.jpg" }) {
                        childImageSharp {
                        fluid(quality: 90, maxWidth: 1920) {
                            ...GatsbyImageSharpFluid_withWebp
                            }
                        }
                    }
                    athletic: file(relativePath: { eq: "3.jpg" }) {
                        childImageSharp {
                        fluid(quality: 90, maxWidth: 1920) {
                            ...GatsbyImageSharpFluid_withWebp
                            }
                        }
                    }
                }
            `}

            render={data => { Object.keys(data).map((image, i ) => {

                    console.log(props.stylesItem[image].name)
                    console.log(image)
                    return (
                        <Col md={4}>
                            <div class="style-box">
                                <StyledBackgroundImage
                                    Tag="div"
                                    className="style-box-img"
                                    fluid={data[image].childImageSharp.fluid}
                                >
                                </StyledBackgroundImage>
                                <div class="style-text-box">
                                    <h5 class="h5">{props.stylesItem[image].style}</h5>
                                    <h3 class="h3 style-description">{props.stylesItem[image].name}</h3>
                                    <div class="extra-style-details">
                                        <p class="style-short-desc">{props.stylesItem[image].tagline}</p>
                                        <p>{props.stylesItem[image].text}</p>
                                        <ul class="hashtag-list">
                                            <li class="style-attribut"></li>
                                        </ul>
                                    </div>
                                </div>
                            </div>
                        </Col>
                        )
                    })
                }
            }
        />
    )
}

export default StyleItem

const StyledBackgroundImage = styled(BackgroundImage)`
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
`

I'm passing in the following props to this component (abc dummy strings for better readability):

    stylesItem: {
            street: {
                style: "// STREET",
                name: "THE CANVAS",
                tagline: "abc",
                text: "abc",
                hashtags: [
                    "abc", "abc", "abc", "abc"
                ]
            },
            casual: {
                style: "// CASUAL",
                name: "THE CLASSIC",
                tagline: "abc",
                text: "abc",
                hashtags: [
                    "abc", "abc", "abc", "abc", "abc", "abc"
                ]
            },
            athletic: {
                style: "// ATHLETIC",
                name: "THE PERFORMER",
                tagline: "abc",
                text: "abc",
                hashtags: [
                    "abc", "abc", "abc", "abc", "abc", "abc"
                ]
            }
        }

I'm using Gatsby's Staticquery to load in 3 images (street, casual, athletic) and want to render the part in the second return statement 3 times (1 for each image), each time with the background image loading in dynamically as well as the content.

The 2 console.log() statements print out as expected.

console.log(props.stylesItem[image].name)
console.log(image)

THE CANVAS
street
THE CLASSIC
casual
THE PERFORMER
athletic

However nothing gets rendered to the screen and I'm not seeing any errors. What am I doing wrong?

Thanks in advance for your help

Your render prop on StaticQuery doesn't return anything, and therefore doesn't render anything.

In the StaticQuery render prop you are mapping over the keys of the queried data, then generating a bunch of JSX successfully. But notice you are not actually doing anything with it because the resulting JSX doesn't get returned.

So the entire StyleItem component does a bunch of work and then doesn't render anything, because the only thing it renders is StaticQuery .

const StyleItem = ({ stylesItem }) => {
  return (
    <StaticQuery
      query={graphql`
        query {
          street: file(relativePath: { eq: "1.png" }) {
            childImageSharp {
              fluid(quality: 90, maxWidth: 1920) {
                ...GatsbyImageSharpFluid_withWebp
              }
            }
          }
          casual: file(relativePath: { eq: "2.png" }) {
            childImageSharp {
              fluid(quality: 90, maxWidth: 1920) {
                ...GatsbyImageSharpFluid_withWebp
              }
            }
          }
          athletic: file(relativePath: { eq: "3.png" }) {
            childImageSharp {
              fluid(quality: 90, maxWidth: 1920) {
                ...GatsbyImageSharpFluid_withWebp
              }
            }
          }
        }
      `}
      render={data => {
        // Make sure to return something here
        return Object.keys(data).map(imageTitle => {
          const fluidProp = data[imageTitle].childImageSharp.fluid
          const imageData = stylesItem[imageTitle]
          return (
            <>
              <StyledBackgroundImage
                Tag="div"
                className="style-box-img"
                fluid={fluidProp}
              ></StyledBackgroundImage>
              <div>
                <h5>{imageData.style}</h5>
                <h3>{imageData.name}</h3>
                <p>{imageData.tagline}</p>
                <p>{imageData.text}</p>
              </div>
            </>
          )
        })
      }}
    />
  )
}

Something worth nothing with Arrow functions is that

when the only statement in an arrow function is return , we can remove return and remove the surrounding curly brackets

(param1, param2, …, paramN) => expression  
// equivalent to: => { return expression; }

So the above render prop on StaticQuery could be further simplified as:

render={data =>
  Object.keys(data).map(imageTitle => {...})
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM