Import react components in gatsby JS

I am building a Gatsby JS blog.
Below is my planning when it comes to what get rendered into the index page.

How do I import the bio.js into layout.js?

layout.js file:

import React from "react"
import PropTypes from "prop-types"
import { StaticQuery, graphql } from "gatsby"

import Header from "./header"
import Footer from "./footer"
import bio from "../pages/bio"
import "./layout.css"

const Layout = ({ children }) => (
  <StaticQuery
    query={graphql`
      query SiteTitleQuery {
        site {
          siteMetadata {
            title
          }
        }
      }
    `}
    render={data => (
      <>
        <Header siteTitle={data.site.siteMetadata.title} />
        <div
          style={{
            margin: `0 auto`,
            maxWidth: 960,
            padding: `0px 1.0875rem 1.45rem`,
            paddingTop: 0,
          }}
        >
          <main>{children}</main>
        </div>
        <bio/>
        <Footer />
      </>
    )}
  />
)

Layout.propTypes = {
  children: PropTypes.node.isRequired,
}

export default Layout

bio.js file:

import React from "react"
import Layout from "../components/layout"
import SEO from "../components/seo"
import profile_pic from "../images/profile_pic.png"
import 'bootstrap/dist/css/bootstrap.css'

const bio = ({data}) => (
  <Layout>
    <SEO title="slowpacedcoding" keywords={[`slowpacedcoding`, `web development`, `Matt Zhou`]} />

    <h3 style={{
      fontFamily: `'Montserrat', sans-serif`,
      fontWeight: 400,
      marginTop:`1rem`,
      color: `#f47c48`,
    }}>Bio</h3>
    <img src={profile_pic} alt="profile_pic" style={{
      width:`100px`,
    }}></img>
    <p style={{
      fontFamily: `'Montserrat', sans-serif`,
    }}>
    Former student of Singapore Polytechnic, dropped out at the end of year two, had been
    learning Web-Development since 2016. My goal is to become a web developer in an English speaking country.
    </p>

    <h5 style={{
      fontFamily: `'Montserrat', sans-serif`,
    }}>Find me at :</h5>

    <div>
      <a href="https://www.linkedin.com/in/xiang-zhou-03547755/" rel='noopener noreferrer' target="_blank" style={{backgroundColor: `#fff5e8`,color:`black`,textDecoration:`none`,}}>LinkedIn</a>
      <a href="https://github.com/zhouxiang19910319" rel='noopener noreferrer' target="_blank"  style={{backgroundColor: `#fff5e8`,color:`black`,textDecoration:`none`,}}>github</a>
      <a href="https://medium.freecodecamp.org/the-most-difficult-things-about-learning-to-code-by-yourself-b24ac8c3c23a "
      rel='noopener noreferrer' target="_blank" style={{backgroundColor: `#fff5e8`,color:`black`,textDecoration:`none`,}}>medium</a>
      <a href="https://twitter.com/zh0ux1ang" rel='noopener noreferrer' target="_blank" style={{backgroundColor: `#fff5e8`,color:`black`,textDecoration:`none`,}}>twitter</a>
      <a href="https://www.freecodecamp.org/zhouxiang19910319" rel='noopener noreferrer' target="_blank" style={{backgroundColor: `#fff5e8`,color:`black`,textDecoration:`none`,}} >freeCodeCamp</a>
    </div>

  </Layout>
)

export default bio

Perhaps make bio.js a full on class component, and add it to your layout.js component. I wouldn’t think you would need to include your layout component directly in your bio component.

So instead of import bio from '../pages/bio' you could export your bio component and import that into your layout component like import { Bio } from '../components/bio'.

Think of it this way. By looking at your design, it would seem to me bio.js should not be a page on its own but rather a component you can sit adjacent to your post component. You could wrap them in a <React.Fragment>` and have something like you’ve designed here.

1 Like

Every component in React need to use Title Case by convention, so change your bio to Bio and use standard import - export will do

1 Like

It’s not just convention – every React component must start with an uppercase letter. Otherwise react will treat it as an HTML tag.

1 Like

new layout.js

import React from "react"
import PropTypes from "prop-types"
import { StaticQuery, graphql } from "gatsby"

import Header from "./header"
import Footer from "./footer"
import {Bio} from "./bio"
import "./layout.css"

const Layout = ({ children }) => (
  <StaticQuery
    query={graphql`
      query SiteTitleQuery {
        site {
          siteMetadata {
            title
          }
        }
      }
    `}
    render={data => (
      <>
        <Header siteTitle={data.site.siteMetadata.title} />
        <div
          style={{
            margin: `0 auto`,
            maxWidth: 960,
            padding: `0px 1.0875rem 1.45rem`,
            paddingTop: 0,
          }}
        >
          <main>{children}</main>
        <Bio />
        </div>
        <Footer />
      </>
    )}
  />
)

Layout.propTypes = {
  children: PropTypes.node.isRequired,
}

export default Layout

bio.js

import React from "react"
// import Layout from "./layout"
// import SEO from "./seo"
// import profile_pic from "../images/profile_pic.png"
import { Component, Fragment } from 'react'
import { constants } from "os"
// import 'bootstrap/dist/css/bootstrap.css'

class Bio extends React.Component{
  render (){
    return(
        <h1>Hello world</h1>
    )
  }
}

export default Bio

These two will get me this error:

×
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it’s defined in, or you might have mixed up default and named imports.

Check the render method of Context.Consumer.

also in the terminal it says:

"export 'Bio' was not found in './bio'

Why you’re doing named import when you’re not doing named export?

It should be this I believe:
import Bio from "./bio"

1 Like

Thanks for the reply and it solved my problem.

Another question:

with both index.js + layout.js present, where do I put the styling of my main page??
I am using react-bootstrap right now.
Should I put everything in layout.js or??
If I do, what should I put in index.js?

This is my current index.js file:

import React from "react"
import { Link } from "gatsby"
import Layout from "../components/layout"
import SEO from "../components/seo"
import 'bootstrap/dist/css/bootstrap.css';
import Container from 'react-bootstrap/Container'
import Row from 'react-bootstrap/Row'
import Col from 'react-bootstrap/Col'



const IndexPage = () => (
  <Layout>
    <SEO title="slowpacedcoding" keywords={[`slowpacedcoding`, `programming`, `Matt Zhou`, `gatsbyJS`,`web development`,`zhouxiang19910319`,`web programming`]} />

    <Container>
      <Row>
        <Col xl={6} lg={6} md={12} sm={12} xs={12}>
          {/* BLOG POST SECTION IS HERE! */}
          <Link to="/blog" style={{textDecoration:`none`,display:`inline-block`}}><h3 style={{
          fontFamily: `'Montserrat', sans-serif`,
          fontWeight: 400,
          color: `#f47c48`,
          marginLeft:`-1rem`,
          }}>Blog Posts</h3></Link>
        </Col>

        <Col xl={6} lg={6} md={12} sm={12} xs={12}>
          {/* BIO SECTION IS HERE! */}
        </Col>
      </Row>
     </Container>


  </Layout>
)

export default IndexPage




If it’s a global stylesheet, like bootstrap.css, I personally tend to keep them in my index.js file, or whatever your root file is.

hmmm, let me be more specific. You could look at the layout that I have on my blog at the top of the thread. The index page should look exactly like the pic above. I used to make Bio.js not a separate file. And I just add that section into the index page and use these to make a duo column layout,

    <Container>
      <Row>
        <Col xl={6} lg={6} md={12} sm={12} xs={12}>
          {/* BLOG POST SECTION IS HERE! */}
          <Link to="/blog" style={{textDecoration:`none`,display:`inline-block`}}><h3 style={{
          fontFamily: `'Montserrat', sans-serif`,
          fontWeight: 400,
          color: `#f47c48`,
          marginLeft:`-1rem`,
          }}>Blog Posts</h3></Link>
        </Col>

        <Col xl={6} lg={6} md={12} sm={12} xs={12}>
          {/* BIO SECTION IS HERE! */}
        </Col>
      </Row>
     </Container>

but right now when I import separate Bio.js file, I got this:

So the duo column styling went missing.

@ husseyexplores

Do you have a github repo link for this project?

Layout.js file looks off to me.
You have this code in the layout container:

render={data => (
      <>
        <Header siteTitle={data.site.siteMetadata.title} />
        <div
          style={{
            margin: `0 auto`,
            maxWidth: 960,
            padding: `0px 1.0875rem 1.45rem`,
            paddingTop: 0,
          }}
        >
          <main>{children}</main>
        <Bio />
        </div>
        <Footer />
      </>
    )}

You are rendering <Bio /> in there, AFTER main.
Are you not supposed to remove <Bio /> from your Layout.js, and render it from your index.js file inside your <Col>?

Your index JS is rendering only Layout component but Layout doesn’t have anything to render apart from empty Row and Col.

Just add your <Bio /> component where you have this comment:
{/* BIO SECTION IS HERE! */}

1 Like

wow. Thank you! It worked!

If I have any questions later I might @ you here, is that okay?

1 Like

Sure! I’d be glad to help whenever I can.