Search code examples
javascriptreactjsgatsby

Gatsby - Nestled Component Not Rendered


Sorry if there's a really simple solution, but building websites isn't my area of expertise.

I'm currently trying to create a Gatsby website where I have a Component nestled inside another Component but it shows a completely blank screen when I try to show the nestled Component. Following the answer from this question, I implemented a Layout Component that serves as a template for every site. In the future, I plan to tidy up the navigation bar and implement that into the Layout Component, but that's an issue for another time.

I'm currently trying to put in a Tile Component into my Layout that is also encapsulated inside my IndexPage, but my screen just shows nothing when I try to run it. I've tried to shorten the code so that it includes the minimum amount required.

I've taken a look at the Gatsby documentation and it appears that under the "Non-page components" section that I should use GraphQL, which I'm not sure how it works.

I suspect that the reason why it isn't working is that the Tile Component has to take in an imgLocation, altText, and caption properties, and somewhere along the way the code isn't working as intended.


Code:

index.js:

import * as React from "react"
import Layout from './Layout.js';
import Tile from './Tile.js';

// markup
const IndexPage = () => {

    return (
        <Layout pageTitle="Home">
                <div id="main">
                    <div className="inner">
                        <h1>
                            <b>Portfolio</b>
                        </h1>
                        <p>
                            Here's all of the work that I've been commissioned to do over the past few years.
                        </p>
                        <h2>
                            <b>Christmas</b>
                        </h2>
                        <h3>
                            <b>Portrait</b>
                        </h3>
                        <section className="tiles">
                            <Tile imgLocation="imageFileLocationGoesHere" altText="descriptionOfImage" caption="Image Description" />
                            <Tile imgLocation="imageFileLocationGoesHere" altText="descriptionOfImage" caption="Image Description" />
                        </section>
                        <br />
                        <h3>
                            <b>Landscape</b>
                        </h3>
                        <section className="tiles">
                            <Tile imgLocation="imageFileLocationGoesHere" altText="descriptionOfImage" caption="Image Description" />
                            <Tile imgLocation="imageFileLocationGoesHere" altText="descriptionOfImage" caption="Image Description" />
                        </section>
                    </div>
                </div>
                {/* Footer */}
                <footer id="footer">
                    {/* footer goes here */}
                </footer>
        </Layout>
    )
}

export default IndexPage;

Tile.js (within the same folder as index.js):

import React from "react";
import '../css/main.css';

const Tile = (props) => {
    const imgLocation = props.imgLocation;
    const altText = props.altText;
    const caption = props.caption;

    return (
        <article>
            <span>
                <img src={require({imgLocation}).default} alt={altText} onClick={() => {openModal(props)}} />
            </span>
            <br />
            <p>{caption}</p>
        </article>
    );
}

export default Tile;

Layout.js (within the same folder as in index.js)

import * as React from 'react';

const Layout = ({pageTitle, children}) => {
    return (
        <main>
                <title>{pageTitle}</title>
                <meta charSet="utf-8" />
                <meta
                    name="viewport"
                    content="width=device-width, initial-scale=1, user-scalable=no"
                />
                {children}
        </main>
    )
}

export default Layout;

Solution

  • The problem you are facing here is that your Tile component is inside the /pages folder as you pointed here:

    Tile.js (within the same folder as index.js):

    So, Gatsby is trying to create a page based on the Tile component, hence, you are trying to render a page inside a page.

    Move your component into another folder such as src/components/Tile and the issue should be gone.

    Layout component also needs to be outside /pages folder.

    Regarding the image, try to import it in the parent component and lift it to the child like:

    import * as React from "react"
    import Layout from './Layout.js';
    import Tile from './Tile.js';
    
    ... 
    
    <Tile imgLocation={'./path/to/your/image.png'} />
    

    And then:

      <img src={imgLocation} alt={altText} onClick={() => {openModal(props)}} />
    

    Or even drilling the image directly:

        import Img from './path/to/your/image.png'
    
       ...
    
        <Tile img={Img} />
    

    Then:

    const Tile = ({img:Img, altText, caption}) => {
    
        return (
            <article>
                <span>
                <Img />
                </span>
                <br />
                <p>{caption}</p>
            </article>
        );
    }
    
    export default Tile;
    

    Reassigning the img props as React component should also do the trick