Basic Gatsby Shopify example missing Layouts - reactjs

I am working with a basic Gatsby Shopify website template here https://www.gatsbyjs.com/docs/building-an-ecommerce-site-with-shopify/
I am trying to get this simple example up and running but I noticed in the following code block in
/src/pages/products.js
import Layout from "../components/layout"
there is no mention of components or layouts in the article and the app is throwing errors there. I am just trying to get a basic example to work. Is there a github link for this code?

The <Layout> component is a common resource in mostly all Gatsby starters (the default one for example), if you don't have it, just create the following structure under /components folder (to keep your code structure):
/**
* Layout component that queries for data
* with Gatsby's useStaticQuery component
*
* See: https://www.gatsbyjs.com/docs/use-static-query/
*/
import React from "react"
import PropTypes from "prop-types"
import { useStaticQuery, graphql } from "gatsby"
import Header from "./header"
import "./layout.css"
const Layout = ({ children }) => {
const data = useStaticQuery(graphql`
query SiteTitleQuery {
site {
siteMetadata {
title
}
}
}
`)
return (
<>
<Header siteTitle={data.site.siteMetadata?.title || `Title`} />
<div
style={{
margin: `0 auto`,
maxWidth: 960,
padding: `0 1.0875rem 1.45rem`,
}}
>
<main>{children}</main>
<footer style={{
marginTop: `2rem`
}}>
© {new Date().getFullYear()}, Built with
{` `}
Gatsby
</footer>
</div>
</>
)
}
Layout.propTypes = {
children: PropTypes.node.isRequired,
}
export default Layout
As you can see, the <Layout> component wraps the whole application with the children prop, sharing a <Header> component and a <footer> tag across all the applications when used.
You can remove propTypes if you are not using them.

Related

How to use gatsby background image plugin

I'm new to gatsby and i'm trying to use gatsby background image plugin but it does not work, the image wont show on screen.
Here's my code :
import * as React from "react"
import { graphql, useStaticQuery } from 'gatsby'
import { createGlobalStyle } from "styled-components"
import BackgroundImage from 'gatsby-background-image'
const GlobalStyle = createGlobalStyle`
body{
background-color: #270A63;
margin : 0px;
display:flex;
}`
const Layout = (props, { children }) => {
const data = useStaticQuery(
graphql`
query {
bgImage : file(relativePath: {eq: "background.png"}) {
childImageSharp {
gatsbyImageData(quality: 90)
}
}
}
`
)
const imageData = data.bgImage.childImageSharp.gatsbyImageData;
return (
<React.Fragment>
<GlobalStyle />
<BackgroundImage
Tag="section"
image={imageData}
>
</BackgroundImage>
</React.Fragment>
)
}
export default Layout
Layout is a custom component that I'm using in index page.
I used console.log to check imageData and it is an object that looks like this :
{bgImage:
childImageSharp:
gatsbyImageData:
backgroundColor: "#680818"
height: 1117
images:
fallback: {src: '/static/32d467ee3060062ab794e34f2002c807/f89cf/background.png', srcSet: '/static/32d467ee3060062ab794e34f2002c807/5829e/bac…60062ab794e34f2002c807/f89cf/background.png 1010w', sizes: '(min-width: 1010px) 1010px, 100vw'}
sources: [{…}]
[[Prototype]]: Object
layout: "constrained"
width: 1010}
I don't understand why it does not work.
Thank you for your help !
As per your GraphQL, you are using a Gatsby version greater or equal than 3. I think your snippet should look like something like:
import React from 'react'
import { graphql, useStaticQuery } from 'gatsby'
import { getImage, GatsbyImage } from "gatsby-plugin-image"
import { convertToBgImage } from "gbimage-bridge"
import BackgroundImage from 'gatsby-background-image'
const GbiBridged = () => {
const { bgImage }= useStaticQuery(
graphql`
query {
bgImage : file(relativePath: {eq: "background.png"}) {
childImageSharp {
gatsbyImageData(quality: 90)
}
}
}
`
)
const image = getImage(bgImage)
const backgroundImage= convertToBgImage(image)
return (
<React.Fragment>
<GlobalStyle />
<BackgroundImage
Tag="section"
{...backgroundImage}
preserveStackingContext
>
<div style={{minHeight: 1000, minWidth: 1000}}>
<GatsbyImage image={image} alt={"testimage"}/>
</div>
</BackgroundImage>
</React.Fragment>
)
}
export default GbiBridged
Modified from: https://www.gatsbyjs.com/plugins/gatsby-background-image/#gatsby-34--gatsby-plugin-image applying your code
Gatsby changed the image plugin from gatsby-image (Gatsby 1 and 2) to gatsby-plugin-image (version 3 onwards). Among other things, it has changed the internal GraphQL nodes of the image data, hence the workaround of using gatsby-background-image has also changed accordingly. In your case, you are using the deprecated version of gatsby-image so your code is not able to display the image.
You can follow the full discussion in this GitHub thread: https://github.com/timhagn/gatsby-background-image/issues/141
I'd recommend not using any external plugins for this but using CSS to achieve this. This way you don't have to learn any new third-party plugins and can use the knowledge you have about CSS. Here's an example from the docs: https://www.gatsbyjs.com/docs/how-to/images-and-media/using-gatsby-plugin-image/#background-images
import * as React from "react"
import { StaticImage } from "gatsby-plugin-image"
export function Hero() {
return (
<div style={{ display: "grid" }}>
{/* You can use a GatsbyImage component if the image is dynamic */}
<StaticImage
style={{
gridArea: "1/1",
// You can set a maximum height for the image, if you wish.
// maxHeight: 600,
}}
layout="fullWidth"
// You can optionally force an aspect ratio for the generated image
aspectRatio={3 / 1}
// This is a presentational image, so the alt should be an empty string
alt=""
// Assisi, Perúgia, Itália by Bernardo Ferrari, via Unsplash
src={
"https://images.unsplash.com/photo-1604975999044-188783d54fb3?w=2589"
}
formats={["auto", "webp", "avif"]}
/>
<div
style={{
// By using the same grid area for both, they are stacked on top of each other
gridArea: "1/1",
position: "relative",
// This centers the other elements inside the hero component
placeItems: "center",
display: "grid",
}}
>
{/* Any content here will be centered in the component */}
<h1>Hero text</h1>
</div>
</div>
)
}

How to override prime-react component CSS styling?

I am using prime-react to style my React page. But I want a more compact website with very few padding and minimum styling. For this purpose, I want to override a few CSS properties for the prime-react components.
For eg, I am trying to reduce the padding for the MenuBar -
HomePage.js
import {React, Component } from 'react';
import { Menubar } from 'primereact/menubar';
import 'primereact/resources/themes/saga-blue/theme.css';
import 'primereact/resources/primereact.min.css';
import 'primeicons/primeicons.css';
import styled from "styled-components";
export default class HomeMenuBar extends Component {
// menu code ...
render() {
return (
<div>
<div className="card">
<Menubar model={this.items} className={this.props.className} />
</div>
</div>
);
}
}
const ComponentView = styled(HomeMenuBar)`
.p-menubar .p-menubar-root-list > .p-menuitem > .p-menuitem-link {
padding: 0.1rem 1rem !important;
}
`;
The above code makes no difference to the original styling.
I am trying to make use of this component.
However, particularly using these styled-components I don't like it. I am new to react and would like to know if there are better alternatives like, storing the CSS properties in another file and then importing it in the required file. I tried this part but it also didn't work out.
I work with react over a year and have seen lot of different ways to customise components and so far, I think that styled-components is the most convenient way to customize components if you cook them right.
I love to put all customized components with styled to a separate file near the index.js called styled.js of Component.js and Componnet.styled.js (in the separate folder of course MyComponent/index.js);
In styled.js you export all components like this:
export const Container = styled.div`
.p-menubar .p-menubar-root-list > .p-menuitem > .p-menuitem-link {
padding: 0.1rem 1rem !important;
}
`
In index.js file you inport them like this:
import {Container} from './styled'
// or import * as Styled from './styled' (if you have a lot of customized components);
export default class HomeMenuBar extends Component {
// menu code ...
render() {
return (
<Container>
<div className="card">
<Menubar model={this.items} className={this.props.className} />
</div>
</Container>
);
}
}
If you want to try something more like classic css try to look at css-modules.
This article can help https://www.triplet.fi/blog/practical-guide-to-react-and-css-modules/
You can also try patch-styles, a more declarative way to apply CSS/SCSS modules to your code. Also, check out the StackBlitz example.

Gatsby Netlify build error: Can't resolve '../components/GridTemplate/GridTemplate.js' in '/opt/build/repo/src/templates'

This started happening suddenly when debugging a seemingly unrelated error on Netlify build. I do not have this issue locally. I've cleared my cache, deleted my package-lock and node module folder and updated everything, as well as ran a build without cache on Netlify. I've checked the file/folder names for case sensitive also. What could it be?
One of the templates the component is used:
import React, { Component } from 'react'
import GridTemplate from '../components/GridTemplate/GridTemplate.js'
import { graphql } from 'gatsby'
...
class Mediums extends Component {
render() {
let allTitles = []
this.props.data.allMarkdownRemark.edges.forEach( post => {
allTitles.push(post.node.frontmatter.title)
})
return (
<div style={{position: "absolute", width: "100%", height: "100%", overflow: "hidden", overflowY: "scroll"}}>
<HeaderMeta subTitle={this.props.pageContext.medium} itemGroup={this.props.data.allMarkdownRemark}/>
<GridTemplate
data={this.props.data.allMarkdownRemark.edges}
title={this.props.pageContext.medium}
pastUrl={this.props.location.pathname}
/>
</div>
)
}
}
export default Mediums
The GridTemplate component:
import React, { Component } from 'react';
import S from './imageGrid.module.sass'
import ArtImage from '../ArtImgae/ArtImage.js'
import Link from 'gatsby-link'
import { arrowSvg } from '../../img/svg-index.js'
import InlineSVG from 'svg-inline-react'
import Header from '../Header/Header.js'
import 'typeface-alegreya-sans-sc'
import 'typeface-cinzel-decorative'
import 'typeface-cinzel'
class GridTemplate extends Component {
render() {
const postLinks = this.props.data.map( post => {
const frontmatter = post.node.frontmatter
return (
<div key={post.node.fields.slug} className={S.imageItem}>
<Link
to={post.node.fields.slug}
//pass prop of cat / med paths for back button on art item
state={{pastUrl: this.props.pastUrl || null}}
>
<h2>{frontmatter.title}</h2>
<ArtImage
fluid={frontmatter.featuredImage.childImageSharp.fluid}
imageData={frontmatter}
/>
</Link>
</div>
)
})
//from context
const title = this.props.title
//const totalCount = this.props.data.allMarkdownRemark.totalCount not used
return (
<section id={S.GridTemplate}>
<div className={S.headerHolder}>
<Header to={["home", "archive"]} white={true} />
</div>
<div className={S.titleHolder}>
<Link to = "/store" className={S.storeLink} >
<InlineSVG src={arrowSvg} />
</Link>
<h1 id={S.mediumTitle}>{title}</h1>
</div>
<div className={S.imageGrid}>
{postLinks}
</div>
</section>
)
}
}
export default GridTemplate
File structure:
The component GridTemplate.js is used by categorys.js and mediums.js
Found it. Turns out my renaming of the path to the component folder to uppercase was never noticed by my Mac OS, despite appearing uppercase. On Githubs end, the path was still lower case, which was wrong. Used this gude to rename from Githubs end.
Try again deployment to netlify after changing import type-
from
import GridTemplate from '../components/GridTemplate/GridTemplate.js'
to
import GridTemplate from '../components/GridTemplate/GridTemplate'
I had the same issue when trying to deploy to Netlify:
can't resolve '../components/search/index' in '/opt/build/repo/src/pages'
My original line was:
import Search from "../components/search/index";
Please notice the lowercase for the directory name search. For some reason I had to rename the folder to uppercase Search, i.e.,:
import Search from "../components/Search/index";
and Netlify would build successfully.

How do I pass a className to a image component in Gatsby

I am using gatsby-image and gatsby-source-filesytem I want the img tag (Logo component) when rendered as html to have a className of logo how do I go about doing this, gatsby-image docs say to pass it through props. I still don't quite understand react, so need help understanding here is my code.
logo.js
import React from "react"
import { StaticQuery, graphql } from "gatsby"
import Img from "gatsby-image"
/*
* This component is built using `gatsby-image` to automatically serve optimized
* images with lazy loading and reduced file sizes. The image is loaded using a
* `StaticQuery`, which allows us to load the image from directly within this
* component, rather than having to pass the image data down from pages.
*
* For more information, see the docs:
* - `gatsby-image`: https://gatsby.app/gatsby-image
* - `StaticQuery`: https://gatsby.app/staticquery
*/
const Image = () => (
<StaticQuery
query={graphql`
query {
placeholderImage: file(relativePath: { eq: "riel-type.png" }) {
childImageSharp {
fluid(maxWidth: 300) {
...GatsbyImageSharpFluid
}
}
}
}
`}
render={data => <Img fluid={data.placeholderImage.childImageSharp.fluid} />}
/>
)
export default Image
index.js
import React from "react"
import { Link } from "gatsby"
import Layout from "../components/layout"
import Image from "../components/image"
import Logo from "../components/logo"
import SEO from "../components/seo"
const IndexPage = () => (
<Layout>
<SEO title="Home" keywords={[`gatsby`, `application`, `react`]} />
<div className="row">
<div className="col-4">
<Logo />
</div>
</div>
</Layout>
)
export default IndexPage
gatsby-image docs say to pass it through props
Means that you can add any property you want inside the Img tag. Because of some internal restriction you have to use the JavaScript name attribute and not the HTML one (ie className instead of class)
So :
render={data => <Img fluid={data.placeholderImage.childImageSharp.fluid} className="logo" />}

HERE Maps React Component shows up as empty

I am attempting to make a small web app with React that involves a map. I'm using the HERE Maps react component (this is non-negotiable) but I'm having trouble getting the map to show up. I'm not sure if it's the Key or my understanding of React (which is small), that's causing the issue.
Map Component
import React from "react";
import { connect } from "react-redux";
import HEREMap from "react-here-maps";
#connect((store) => {
return {
};
})
export default class Map extends React.Component {
render() {
console.info(HEREMap);
const style = {
width: "100%",
height: "100%"
};
return <div style={style}>
<h1>Hello HERE</h1>
<HEREMap
appId="<ID>"
appCode="<CODE>"
center={{ lat: 51.5, lng: 0 }}
zoom={14}
/>
</div>
};
};
Main
import React from "react"
import ReactDOM from "react-dom"
import { Provider } from "react-redux"
import Map from "./components/Map"
import Layout from "./components/Layout"
import store from "./store"
const app = document.getElementById('app')
ReactDOM.render(
<Provider store={store}>
<Map />
</Provider>, app);
I noticed this in you code listing:
const style = {
width: "100%",
height: "100%"
};
A common problem is that the height of a block element like <div> defaults to the height of the block's content. By specifying it as a percentage like 100%, it will be the height of the element's parent which if it's just an empty container with no content will have a height of 0 and therefore not be visible.
The answers in Percentage Height HTML 5/CSS might be helpful for finding alternatives like setting the height of the body element.
There may also be something else going on as the react-here-maps package has a few issues, but you said that wasn't negotiable. For anybody else looking for a more standalone demonstration, the Use HERE Interactive Maps with ReactJS to Pick a Theme might be helpful. In the source example there, the height is fixed at 400px.

Resources