Material that i Used
・Contentful
・Gatsby
・Graphql
Success
Got a Content from Contentful By using a 8000_graphql and show up on local URL(http://localhost:8000/)
Fail
Switched out a page URL(http://localhost:8000/) to
URL(http://localhost:8000/blog/....) that shows up 404 pages.
Error
warn The GraphQL query in the non-page component "C:/Users/taiga/Github/Gatsby-new-development-blog/my-blog/src/templates/blog.js" will not
Exported queries are only executed for Page components. It's possible you're
trying to create pages in your gatsby-node.js and that's failing for some
reason.
If the failing component(s) is a regular component and not intended to be a page
component, you generally want to use a <StaticQuery> (https://gatsbyjs.org/docs/static-query)
instead of exporting a page query.
blog.js
import React from 'react';
import { graphql } from 'gatsby';
import Layout from '../components/layout';
import Nav from '../components/nav';
import SEO from '../components/seo';
import './blog.css';
const BlogTemplate = (props) => {
return (
<Layout>
<SEO title={props.data.contentfulBlog.seoTitle} description={props.data.contentfulBlog.seoDescription} keywords={props.data.contentfulBlog.seoKeywords} />
<Nav />
<div className='blog__header'>
<div className='blog__hero' style={{backgroundImage: `url(${props.data.contentfulBlog.featuredImage.fluid.src})`}}></div>
<div className='blog__info'>
<h1 className='blog__title'>{props.data.contentfulBlog.title}</h1>
</div>
</div>
<div className='blog__wrapper'>
<div className='blog__content'>
<div dangerouslySetInnerHTML={
{__html: `${props.data.contentfulBlog.content.childMarkdownRemark.html}`}
} />
</div>
</div>
</Layout>
)
}
export default BlogTemplate;
export const query = graphql`
query BlogTemplate($id: String!) {
contentfulBlog(id: {eq: $id}) {
title
id
slug
content {
childMarkdownRemark {
html
}
}
seoTitle
seoDescription
seoAuthor
seoKeywords
seoImage {
fluid(maxWidth: 1200, quality: 100) {
...GatsbyContentfulFluid
src
}
}
featuredImage {
fluid(maxWidth: 1200, quality: 100) {
...GatsbyContentfulFluid
src
}
}
}
}
`
Related
I am trying to do a POST method using ApolloGraphql Mutation into my local postgres database. I am able to query and my api works when I am adding a new item via the Apollo Graphql Client, but am trying to figure out a way to post via a form.
import type { NextPage } from 'next'
import Head from 'next/head'
import {Card} from "../components/Card"
//import {products} from "../data/products";
import {gql, useQuery, useMutation} from "#apollo/client"
import { useState } from 'react';
const AllProductQuery = gql`
query Product_Query {
products {
title
description
}
}
`;
const AddProducts = gql`
mutation Add_Product($title: String!
$description: String!
) {
product(description: $description, title: $title) {
id
description
title
}
}
`;
const Home: NextPage = () => {
const {data, error, loading} = useQuery(AllProductQuery);
const [title, setTitle] = useState("")
const [description, setDescription] = useState("")
const [createPost] = useMutation(AddProducts, {
variables: {
title,
description
}
});
if (loading) {return <p>Loading...</p>}
if(error) {return <p>{error.message}</p>}
return (
<div >
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<div className='container mx-auto my-20 px-5 '>
{data.products.map((product: any) => (
<Card key={product.id} title={product.title} description={product.description} />
))}
</div>
<form className='flex flex-col p-2' onSubmit={e => {
e.preventDefault(); createPost();
}}>
<input placeholder="Title" type='text' value={title}onChange={(e) => {setTitle(e.target.value);}} required/>
<input placeholder="Description" type='text' value={description} onChange={(e) => {setDescription(e.target.value);}} required/>
<button type="submit" className='bg-blue-500 text-white rounded-lg'>Submit</button>
</form>
</div>
)
}
export default Home
I am currently creating a [createPost] with a useMutation function and putting my variables as title and description. In the form I then apply that method. Any help would be great!
I'm running into an issue where I've created a non page component with a StaticQuery that is pulling information with a set up like this.
const BestSellers = () => (
<div>
<StaticQuery
query={bestSellerQuery}
render={data => (
<div>
{data.allMarkdownRemark.edges.map(({ node }) => (
<Card className="m-2 index-card" key={node.id}>
<Link to={node.fields.slug}>
<GatsbyImage
className="card-img-top"
image={node.frontmatter.image}
alt={node.frontmatter.description}
/>
</Link>
<hr />
<CardBody>
<Link to={node.fields.slug}>
<CardTitle className="h4 text-light text-wrap">
{node.frontmatter.title}
</CardTitle>
</Link>
<CardSubtitle>{node.frontmatter.description}</CardSubtitle>
{/* <CardSubtitle>{node.excerpt}</CardSubtitle> */}
<CardSubtitle className="float-left mt-5">
Price: ${node.frontmatter.price}
</CardSubtitle>
<CardSubtitle>
<Badge color="danger float-right mt-5">
{node.frontmatter.tag}
</Badge>
</CardSubtitle>
</CardBody>
</Card>
))}
</div>
)}
/>
</div>
);
const bestSellerQuery = graphql`
query bestSellerQuery {
allMarkdownRemark(
filter: { frontmatter: { tag: { eq: "popular" }}}
sort: { fields: [frontmatter___date], order: DESC }
limit: 2
) {
edges {
node {
id
frontmatter {
title
description
price
tag
image {
childImageSharp {
gatsbyImageData(
layout: CONSTRAINED
height: 600
placeholder: BLURRED
formats: [AUTO, JPG]
transformOptions: { fit: COVER, cropFocus: ATTENTION }
)
}
}
}
fields {
slug
}
excerpt
}
}
}
}
`
export default BestSellers;
What I'm doing is my pages are being created programmatically from a Markdown file once it is clicked on so I'm trying to import this into the template that i use to create pages and it just shows loading(static query) I've tried using this same query in pages that do and don't have a page query on them and it results in the same as using this in the template component that I'm trying to use it in.
It was the issues in the graphql query which was being used more specifically the line
filter: { frontmatter: { tag: { eq: "popular" }}}
the issue was the "popular" in the MD file is in caps so by changing it to "POPULAR" that solved it....
I'm building a simple blog with GatsbyJS using Contentful. I have a blogpage with the list of all posts with titles and dates. I want to add, just for the last post, the first lines of the article and the image used in the article.
...
import React from 'react'
import Layout from '../components/layout'
import { Link, graphql, useStaticQuery } from 'gatsby'
import { documentToReactComponents } from "#contentful/rich-text-react-renderer"
import blogStyles from './blog.module.scss'
import Head from '../components/head'
import TransitionLink from "gatsby-plugin-transition-link"
import AniLink from "gatsby-plugin-transition-link/AniLink"
const BlogPage = () => {
const data = useStaticQuery(graphql`
query{
allContentfulBlogPost (sort: { fields: publishedDate, order: DESC}){
edges{
node{
title
slug
publishedDate(formatString:"MMMM Do, YYYY")
}
}
}
}
`)
return (
<Layout>
<Head title = "Post" />
<h1>Post</h1>
<ol data-sal="slide-up" data-sal-delay="300" data-sal-easing="ease"
className={blogStyles.posts}>
{data.allContentfulBlogPost.edges.map((edge) => {
return (
<li className={blogStyles.post}>
<Link to={`/blog/${edge.node.slug}`}>
<h2>{edge.node.title}</h2>
<p>{edge.node.publishedDate }</p>
</Link>
</li>
)
})}
</ol>
</Layout>
)
}
export default BlogPage
Note: I've assumed you mean latest post, instead of last post.
You could use Aliases to split your query into two parts.
latestArticle has a limit: 1 and queries for the extra fields needed for the first lines of the article and the image used in the article (as well as title, slugExt, publishDate).
allOtherArticles has a skip: 1 and just queries for title, slugExt, publishDate.
const BlogPage = () => {
const { latestArticle, allOtherArticles } = useStaticQuery(graphql`
query MyQuery {
latestArticle: allContentfulBlogPost(sort: {order: DESC, fields: publishDate}, limit: 1) {
nodes {
title
slug
publishDate
excerpt {
excerpt
}
thumbnailImage {
imageFile {
id
fluid {
...GatsbyContentfulFluid
}
}
}
}
}
allOtherArticles: allContentfulBlogPost(sort: {order: DESC, fields: publishDate}, skip: 1) {
nodes {
title
slug
publishDate
}
}
}
`)
const latest = latestArticle.edges[0].node
return (
<Layout>
<ol data-sal="slide-up" data-sal-delay="300" data-sal-easing="ease" className={blogStyles.posts}>
<li className="latest-post">
<Link to={`/blog/${latest.slug}`}>
<h2>{latest.title}</h2>
<p>{latest.excerpt.excerpt}</p>
<Img fluid={latest.thumbnailImage.imageFile.fluid} />
</Link>
</li>
{allOtherArticles.edges.map((edge) => {
return (
<li className={blogStyles.post}>
<Link to={`/blog/${edge.node.slug}`}>
<h2>{edge.node.title}</h2>
<p>{edge.node.publishedDate }</p>
</Link>
</li>
)
})}
</ol>
</Layout>
)
}
export default BlogPage
The other option is to just query for all the fields you need. When you map over the data you can check the index and conditionally render the thumbnail and the excerpt (as well as the other stuff).
{data.allContentfulBlogPost.edges.map((edge, index) => {
const firstArticle = index === 0
return (
<li className={ blogStyles.post }>
<Link to={ `/blog/${edge.node.slug }`}>
{ firstArticle && (<Img fluid={edge.node.thumbnailImage.imageFile.fluid } />)}
<h2>{ edge.node.title }</h2>
{ firstArticle && (<p>{ edge.node.title }</p>)}
<p>{ edge.node.publishedDate }</p>
</Link>
</li>
)
})}
I'm building my website with GatsbyJS and graphsql. On my projects site I want to display a grid with Images that Link to further sites.
In order to do that I need to query multiple images. I created a folder in my images folder called "portfolio" and I want to query all the pictures in there.
I have used useStaticQuery before but I've read that currently it's only possible to query one instance so I tried doing it like this, but the code is not working. Any help? Thanks a lot!
import React from 'react'
import Img from 'gatsby-image'
import { graphql } from 'gatsby'
const Portfolio = ({data}) => (
<>
{data.allFile.edges.map(image => {
return (
<div className="sec">
<div className="portfolio">
<div className="containerp">
<Img className="centeredp" fluid={image.node.childImageSharp.fluid}/>
</div>
</div>
</div>
) })}
</>
)
export default Portfolio
export const portfolioQuery = graphql`
{
allFile(filter: {relativeDirectory: {eq: "portfolio"}}) {
edges {
node {
id
childImageSharp {
fluid(maxWidth: 500) {
...GatsbyImageSharpFluid
}
}
}
}
}
}
`;
Is it possible that you have some images missing, so none are rendering?
You could try checking that the image is present before rendering the Img, like this:
{image.node.childImageSharp &&
<Img className="centeredp" fluid={image.node.childImageSharp.fluid}/>}
NB:
If you like, you could also make it a bit clearer by assigning your mapping object (edges) to a variable. It doesn't make that much difference in this example but can be clearer if you have more going on in your component.
E.g.
const Portfolio = ({data}) => (
<>
const images = data.allFile.edges
{images.map(image => {
return (
<div className="sec">
<div className="portfolio">
<div className="containerp">
<Img className="centeredp" fluid={image.node.childImageSharp.fluid}/>
</div>
</div>
</div>
) })}
</>
)
It's most likely that you probably need to set up your 'gatsby-source-filesystem' to recognize images within a query.
in your gatsby-config.js:
{
resolve: gatsby-source-filesystem,
options: {
name: images,
path: ./src/images/,
},
},
GOAL: use Gatsby to render Drupal 8 images associated with nodes
I can render the default Drupal 8 Article node info just fine using a GraphQL query. I cannot get the default image field to render (field_image) - it just renders the url of the image. So I'm almost there but definitely missing something fundamental. Help please?
import React from "react"
import { Link, graphql } from "gatsby"
import Img from "gatsby-image"
const BlogPage = ({data}) => (
<div>
<h1>Know What Grinds My Gears?</h1>
{ data.allNodeArticle.edges.map(
(
{ node }) => (
<div>
#the next Img line doesn't work (renders nothing)
<Img fluid={ node.relationships.field_image.uri.url } />
<h3> { node.title } </h3>
<div dangerouslySetInnerHTML={{ __html: node.body.summary }} />
<Link to= { node.id } >read</Link>
#the next <figure> line doesn't work (renders correct url to image file)
<figure> { node.relationships.field_image.uri.url }</figure>
</div>
)
)
}
</div>
)
export default BlogPage
export const query = graphql`
query allNodeArticle {
allNodeArticle {
edges {
node {
id
title
body {
value
format
processed
summary
}
relationships {
field_image {
uri {
value
url
}
}
}
}
}
}
}
`
what am I doing wrong?
The way we manage this is by having on the GraphQL of the node image:
field_image {
relationships {
field_media_image {
localFile {
publicURL
childImageSharp {
fluid(maxWidth: 520 maxHeight: 520, cropFocus: CENTER) {
...GatsbyImageSharpFluid
}
}
}
}
}
}
And then using it as
<Img
fluid={
data.nodePage.relationships.field_image.relationships.field_media_image.localFile.childImageSharp.fluid
}
/>