Search code examples
reactjsstyled-components

Component content not imported when importing styled components


I am building a site using React and have decided to use Styled Components. I have a component that is styled with Styled Components and is receiving a prop from my homepage where I am using an instance of this component. I have the styling being pulled into the homepage, but it is not pulling in the content of the component. When if I just pull in the whole component it pulls in the content fine, but it doesn't allow me to pass the prop, but if I import the component styling it doesn't pull in the content of the component, but the prop passes properly. So I need some help with how to pull in the content and styling and get the prop to pass.

I am pretty new to Gatsby and Styled Components so thanks for any help.

My Component Code

import React from 'react'
import styled from "styled-components"
import { useStaticQuery, graphql } from 'gatsby'

export const WhyChooseSection = styled.section`
  border-bottom: 1px solid var(--charcoal);
`

export const WhyChooseH2 = styled.h2`
  display: ${(props) => props.displayH2};
  text-align: center;
`

export const WhyChooseContent = styled.div`
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  width: 100%;
  max-width: 1160px;
  margin: 0 auto;
  padding-top: 40px;
  padding-bottom: 40px;
  column-gap: 100px;
  row-gap: 30px;

  @media(min-width: 992px) {
    justify-content: space-between;
    column-gap: 0;
  }

  .why-icon {
    width: 180px;
    height: 145px;
    text-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 20px;

    p {
      margin-bottom: 0;
      font-size: 19px;
      font-weight: var(--font-bold);
    }
  }
`

export function WhyChooseIcons() {
  const data = useStaticQuery(graphql`
    {
      whyChooseIcons: allWp {
        nodes {
          acfOptionsOfficeSettings {
            whyChooseInteriorDetails {
              whyChooseIcons {
                whyChooseIconGraphic {
                  altText
                  id
                  sourceUrl
                }
                whyChooseIconTitle
              }
            }
          }
        }
      }
    }
  `)

  return (
    <>
    {data.whyChooseIcons.nodes.map((node, index) => (
      <WhyChooseSection key={index}>
        <WhyChooseH2>Why Choose Interior Details?</WhyChooseH2>
        <WhyChooseContent>
          {node.acfOptionsOfficeSettings.whyChooseInteriorDetails.whyChooseIcons && node.acfOptionsOfficeSettings.whyChooseInteriorDetails.whyChooseIcons.map((item) => (
            <div className='why-icon' key={item.whyChooseIconGraphic.id}>
              <img src={item.whyChooseIconGraphic.sourceUrl} alt={item.whyChooseIconGraphic.altText} />
              <p>{item.whyChooseIconTitle}</p>
            </div>
          ))}
        </WhyChooseContent>
      </WhyChooseSection>
    ))}
    </>
  )
}

export default WhyChooseIcons

My Homepage Code

import * as React from "react"
// import styled from "styled-components"
import { graphql } from 'gatsby'

import Seo from "../components/seo"
import Hero from '../components/heroComponent'
import { WhyChooseSection } from '../components/whyChooseIcons'
import { WhyChooseH2 } from '../components/whyChooseIcons'
import { WhyChooseContent } from '../components/whyChooseIcons'
import HomeProducts from '../components/homeProducts'
import HomeTestimonials from '../components/testimonials'
import HomeNewHomes from '../components/homeNewHomes'
import HomeFamilyTreatment from '../components/homeFamilyTreatment'
import HomeSolutions from '../components/homeSolutions'
import HomeMotorization from '../components/motorizationComps'
import HomeBrands from '../components/homeBrands'
import CTAOne from '../components/ctaOne'

const IndexPage = (hero) => {
  const heroData = hero.data.homeHero

  return (
    <>
      {heroData.edges.map(({ node }, index) => (
        <Hero key={index} heroTitle={node.template.homePage.heroH1} heroSubTitle={node.template.homePage.heroParagraph} heroBg={node.template.homePage.heroBackground.gatsbyImage} heroBtnOneText={node.template.homePage.heroButton1Text} heroBtnOneURL={node.template.homePage.heroButton1Url} heroBtnTwoText={node.template.homePage.heroButton2Text} heroBtnTwoURL={node.template.homePage.heroButton2Url} />
      ))}
      <WhyChooseSection>
        <WhyChooseH2 displayH2="none"></WhyChooseH2>
        <WhyChooseContent></WhyChooseContent>
      </WhyChooseSection>
      <HomeProducts />
      <HomeTestimonials />
      <HomeNewHomes />
      <HomeFamilyTreatment />
      <HomeSolutions />
      <HomeMotorization />
      <HomeBrands />
      <CTAOne />
    </>
  )
}

export default IndexPage

export const Head = () => <Seo title="Home" />

export const HeroContent = graphql`
  {
    homeHero: allWpPage(filter: {template: {templateName: {eq: "Home Template"}}}) {
      edges {
        node {
          template {
            ... on WpHomeTemplate {
              homePage {
                heroH1
                heroParagraph
                heroButton1Text
                heroButton1Url
                heroButton2Text
                heroButton2Url
                heroBackground {
                  gatsbyImage(placeholder: BLURRED, width: 1920)
                  altText
                }
              }
            }
          }
        }
      }
    }
  }
`

Solution

  • Since you only want to pass a prop into your <WhyChooseIcons> component and that the component itself renders its own content, there is no need to provide any children node to it in the consuming parent.

    Simply update your <WhyChooseIcons> component to accept a prop that it will pass to its inner child. Let's name it displayH2 and we can simply pass it into the <WhyChooseH2> component by doing this: <WhyChooseH2 displayH2={displayH2}>. So your component definition now looks like this:

    export function WhyChooseIcons({ displayH2 }) {
      // Rest of the component logic here
    
      return (
        <>
        {data.whyChooseIcons.nodes.map((node, index) => (
          <WhyChooseSection key={index}>
            <WhyChooseH2 displayH2={displayH2}>Why Choose Interior Details?</WhyChooseH2>
            {/* Other content here */}
          </WhyChooseSection>
        ))}
        </>
      )l
    };
    

    Then in the file where you consume this component, it is just a matter of passing "none" to the prop:

    <WhyChooseSection displayH2="none">
    

    HOWEVER this feel like a XY problem to me, because all you want is to control the conditional rendering of this component. What you can do is to create a prop on your component that determines whether <WhyChosseH2> should be rendered or not.

    export const WhyChooseH2 = styled.h2`
      text-align: center;
    `
    
    export function WhyChooseIcons({ shouldHideH2 }) {
    
      return (
        <>
        {data.whyChooseIcons.nodes.map((node, index) => (
          <WhyChooseSection key={index}>
            {!shouldHideH2 && <WhyChooseH2>Why Choose Interior Details?</WhyChooseH2>}
            {/* Other content here */}
          </WhyChooseSection>
        ))}
        </>
      )
    }
    

    Then you can just control H2 rendering with a true/false boolean:

    {/* To show it, just don't set the prop */}
    <WhyChooseIcons />
    
    {/* To hide it, both ways are valid */}
    <WhyChooseIcons shouldHideH2 />
    <WhyChooseIcons shouldHideH2={true} />