gatsbyjs, reactjs - why components are rendering twice and images do not appear? - reactjs

I am new to gatsbyjs and using v2.
I've 3 components - loader, header and layout.
layout.js
import React from "react"
import Helmet from 'react-helmet'
import { StaticQuery, graphql } from 'gatsby'
import Header from "./header"
import Loader from "./loader"
import 'bootstrap/dist/css/bootstrap.min.css'
import "./layout.module.css"
const Layout = ({ children }) => (
<StaticQuery
query={graphql`
query SiteTitleQuery {
site {
siteMetadata {
title
menuLinks {
name
link
}
}
}
}
`}
render={data => (
<React.Fragment>
<Helmet
title={'tite'}
meta={[
{ name: 'description', content: 'Sample' },
{ name: 'keywords', content: 'sample, something' },
]}
>
</Helmet>
<Loader />
<Header menuLinks={data.site.siteMetadata.menuLinks} siteTitle={data.site.siteMetadata.title} />
<div>{children}</div>
</React.Fragment>
)}
/>
)
export default Layout
In index.js
import React from 'react'
import Layout from "../components/layout"
export default () => (
<Layout>
</Layout>
)
Every component is being rendered twice as shown in screenshot.
Another issue I am facing with images. All the images are in src/images/ and when I use it as below in header component:
import React from "react"
import { Link } from 'gatsby'
import styles from "./layout.module.css"
const logo = 'src/images/logo.png';
const Header = ({ siteTitle, menuLinks }) => (
<header className={styles.header_area}>
<nav className={`${styles.navbar} navbar-expand-lg ${styles.menu_one} ${styles.menu_four}`}>
<div className="container">
<a className="navbar-brand sticky_logo" href="#">
<img src={logo} alt="logo" />
The image doesn't show up on a page. I checked Source in chrome developer tools and found that images are not being served via webpack.
So, why components render twice and why image doesn't show up ? what am I missing or doing worng here ?

I had the same issue when using the gatsby-plugin-layout plugin. The doc is not really clear, but when using the gatsby-plugin-layout plugin, you don't need to wrap your page between the Layout component. That plugin takes care of this automatically. If you explicitly wrap your JSX between the Layout component, the Layout is rendered twice.

I'm not sure why your page is loading double components, are you coming to the site directly, or from another path?
For your image not showing up, this is why:
Everything in your src folder is meant to be dynamic, meaning it won't be served directly. If you want to include image statically, you can create a public folder in your root directory (at the same level with src folder), and put images in there. Anything in this public folder will be served directly. So for example, you can have this structure:
|-- src
`-- public
`-- images
`-- logo.png
Then in your code, you can include the path like
<img src="/images/logo.png" alt="logo" />
I think for a logo like your use case, this method is sufficient. However, if you always link images like this, you'll be missing out a lot of gatsby's cool feature. For example, gatsby can load your image lazily, or optimize the file size! You can learn more here (gatsby official blog).

Related

Issue with rendering images on Gatsby site deployed to github pages [duplicate]

I am having trouble getting images to display on github pages. I am using a repository based page. I have added in a simple img tag with in the JSX and tried using the method described in the Gatsby documentation. I feel like I'm missing something obvious.
Here is the code
import React, { useContext } from 'react';
import AnchorLink from 'react-anchor-link-smooth-scroll';
import { ThemeContext } from 'providers/ThemeProvider';
import { Header } from 'components/theme';
import { Container, Button } from 'components/common';
import dev from 'assets/illustrations/dev.svg';
import { Wrapper, IntroWrapper, Details, Thumbnail } from './styles';
import { withPrefix } from 'gatsby'
import HeadShotPlaceHolder from 'assets/images/HeadShotPlaceHolder.jpeg'
export const Intro = () => {
const { theme } = useContext(ThemeContext);
console.log(HeadShotPlaceHolder)
return (
<Wrapper>
<Header />
<IntroWrapper as={Container}>
<Details theme={theme}>
{/* <h1>Hi There!</h1> */}
<h1>Pamela Welch</h1>
{/* <h4>I’m John and I’m a JAMStack engineer!</h4> */}
<h4>A proven professional with extensive experience in all facets of communication and marketing.</h4>
<Button as={AnchorLink} href="#contact">
Hire me
</Button>
</Details>
<Thumbnail>
{/* This is where the image tag giving me the problem is */}
<img src={ withPrefix(HeadShotPlaceHolder) } alt="I’m John and I’m a JAMStack engineer!" />
</Thumbnail>
</IntroWrapper>
</Wrapper>
);
};
and here is the result
Image Link Broken
Your code looks good, your image has its path prefixed. However, to make it effective you need to run the following snippet in the deploy command:
{
"scripts": {
"deploy": "gatsby build --prefix-paths && gh-pages -d public"
}
}
Note the --prefix-paths flag.
More information in How Gatsby Works in GitHub Pages.

How to implement Server Sider Rendering (SSR) for a NextJS component?

I want to implement Server Sider Rending SSR for a NextJS Typescript component. It's possible to do SSR for a page using getServerSideProps but not found any way for non page child components. It works fine under page folder but no luck outside of page components.
Say I have created a component with API under components folder, here getServerSideProps is not working and even SSR also not working. and can't see the content in page view source DOM.
/components/user.tsx
import React from 'react';
import {useEffect,useState} from 'react';
interface User {
id:number;
name: string;
username: string;
email:string;
}
const Users = () => {
const [data,setData]= useState([])
useEffect(()=>{
fetch("https://jsonplaceholder.typicode.com/users").then((result)=>{
result.json().then((resp)=>{
setData(resp);
})
})
},[])
console.log(data)
return (
<div>
<ul>
{data.map((data: User)=>
<li key={data.id}>
<h2>{data.name}</h2>
<h3>{data.username}</h3>
<h4>{data.email}</h4>
</li>
)}
</ul>
</div>
)
}
export default Users
/pages/user.tsx
import React from 'react';
import Users from "../components/Users";
function user() {
return (
<section>
<h1>User - Component</h1>
<main>
<Users />
</main>
</section>
);
};
export default user;
Can you please help how to implement SSR for components which located out side of pages folder?
As it notes in the documentation
getServerSideProps can only be exported from a page. You can’t export it from non-page files.
This rules out getServerSideProps, now for the ask itself
Two options
setup a corresponding pages/component page
Setup a custom server and use the following in next.config.js - This allows routing to be on you without using the pages as the only place things get served from.
module.exports = {
useFileSystemPublicRoutes: false,
}

images on Gatsby.js site won't display on GitHub pages

I am having trouble getting images to display on github pages. I am using a repository based page. I have added in a simple img tag with in the JSX and tried using the method described in the Gatsby documentation. I feel like I'm missing something obvious.
Here is the code
import React, { useContext } from 'react';
import AnchorLink from 'react-anchor-link-smooth-scroll';
import { ThemeContext } from 'providers/ThemeProvider';
import { Header } from 'components/theme';
import { Container, Button } from 'components/common';
import dev from 'assets/illustrations/dev.svg';
import { Wrapper, IntroWrapper, Details, Thumbnail } from './styles';
import { withPrefix } from 'gatsby'
import HeadShotPlaceHolder from 'assets/images/HeadShotPlaceHolder.jpeg'
export const Intro = () => {
const { theme } = useContext(ThemeContext);
console.log(HeadShotPlaceHolder)
return (
<Wrapper>
<Header />
<IntroWrapper as={Container}>
<Details theme={theme}>
{/* <h1>Hi There!</h1> */}
<h1>Pamela Welch</h1>
{/* <h4>I’m John and I’m a JAMStack engineer!</h4> */}
<h4>A proven professional with extensive experience in all facets of communication and marketing.</h4>
<Button as={AnchorLink} href="#contact">
Hire me
</Button>
</Details>
<Thumbnail>
{/* This is where the image tag giving me the problem is */}
<img src={ withPrefix(HeadShotPlaceHolder) } alt="I’m John and I’m a JAMStack engineer!" />
</Thumbnail>
</IntroWrapper>
</Wrapper>
);
};
and here is the result
Image Link Broken
Your code looks good, your image has its path prefixed. However, to make it effective you need to run the following snippet in the deploy command:
{
"scripts": {
"deploy": "gatsby build --prefix-paths && gh-pages -d public"
}
}
Note the --prefix-paths flag.
More information in How Gatsby Works in GitHub Pages.

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" />}

How To Add My Own Svg Image Just Like Logo Is Shown By Default In Create-React-App

I've got a clean create-react-app install and I wanted to add my own svg image to show, the same way that logo is shown i.e.:
import logo from './logo.svg';
{logo}
However when I import my own svg the same way as logo is imported and try to use it, it prints a url like this on the screen:
/static/media/menu.92677579.svg
instead or rendering the image, could someone help me figure this out please?
When you write {logo} you're just embedding a URL.
If you want to show an image, use the <img> tag like the default template does.
<img src={logo} alt="My logo" />
Hope this helps!
import { ReactComponent as Logo } from './logo.svg';
function App() {
return (
<div>
{/* Logo is an actual React component */}
<Logo />
</div>
);
}
This is a new special syntax when importing SVG in React. The ReactComponent import name is special and tells Create React App that you want a React component that renders an SVG, rather than its filename. You can read more about it here, but keep in mind that this is a React library special syntax:
Reference link: Create React App
I found I could pass in the logo image file (.svg) as a prop from the component "calling ClsSplash". The import in the calling component sent a reference to some sort of optimized svg file at /static/media/logo.5d5d9eef.svg I have no idea where that is or why it is necessary. In any case, I see an animation working referring to that prop.
My ClsSplash is the guts of the default APP.tsx you get when you make a new project with
npx create-react-app hello-world --typescript
I set up another JSX image tag to see how to import the svg file directly within the ClsSpash component. This is works for me running (F5) a "project" within VS2019 launched with IISExpress into Google Chrome 75.0.3770.142 (Official Build) (64-bit)
import * as React from 'react';
import * as logo from './../../logo.svg';
/* imported item has to have the same name as the file name (without extension) */
/* fyi article explains the optimized svg */
/* https://react.christmas/2018/18 to handle a Data URL */
import '../../fldrAppearance/fldrCSS/App.css'; /* for div classname attributes */
class ClsSplash extends React.Component<any, any> {
constructor(props: any)
{
super(props);
}
public componentDidMount()
{
// console.log("logoPath is " + logo);
}
public render()
{
const lclLogo = logo;
console.log("prop logoPath is " + this.props.svg);
return (
<div className="App">
<header className="App-header">
{/*}<img src={logo} className="App-logo" alt="logo" /> {*/}
<img src={`${lclLogo}`} className="App-logo" alt="logo" />
<img src={`${this.props.svg}`} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.tsx</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header >
</div>
)
}
}
export default ClsSplash;
screenshot of two spinning logo svg images

Resources