...GatsbySanityImageFluid - Cannot read property 'fluid' of null - graphql

I'm working with Sanity and Gatsby
I'm trying to map over an array of images to display them in an image gallery. My GraphQL query is working, I am able to display a single image but I receive the error: TypeError: Cannot read property 'fluid' of null When I attempt to map over the array.
Any direction is greatly appreciated!
My Query:
{
sanityGallery {
images {
asset {
fluid {
...GatsbySanityImageFluid
}
}
}
}
}
This Works:
const images = data.sanityGallery.images
<Img className="grow" fluid={images[0].asset.fluid} />
This Does not:
const images = data.sanityGallery.images
<div className="img-container">
{images.map((image, index) => {
console.log(image.asset.fluid); // <-- when adding this it logs the info in the screenshot below
return (
<div className="box">
<Img className="grow" fluid={image.asset.fluid} key={index} />
</div>
)
})}
</div>

Try something like:
const images = data.sanityGallery.images
<div className="img-container">
{images.map((image, index) => {
console.log(image.asset); //
return (
<div className="box">
{image.asset && <Img className="grow" fluid={image.asset.srcSet} key={index} />}
</div>
)
})}
</div>

Related

Problem with pulling data from Graphql into Gatsby

I'm pretty new here to gatsby/programming and i was playing around with the gatsby. I have below issue and I would appreciate if you could let me know where does it goes wrong? Below is my code.
Problem 1: Why i can't return/access the {post1.categories.nodes.name} ? It shows nothing on my page.
Note that there was no problem for me to access {post.video.videoSource} so i guess my Graphql worked fine but when i tried with {post1.categories.nodes.name}, it was literally blank.
Any suggestions? Thank you very much.
const BlogIndex = ({
data,
pageContext: { nextPagePath, previousPagePath },
}) => {
const posts = data.allWpPost.nodes
if (!posts.length) {
return (
<Layout isHomePage>
<Seo title="All posts" />
<Bio />
<p>
No blog posts found. Add posts to your WordPress site and they'll
appear here!
</p>
</Layout>
)
}
return (
<Layout isHomePage>
<Seo title="All posts" />
{/* <Bio /> */}
<Grid container rowSpacing={5} column spacing={5}>
<Grid item xs={12} sm={3} md={3} lg={3}>
<Paper>
<ol style={{ listStyle: `none` }}>
{posts.map(post1 => {
return <li>{post1.categories.nodes.name}</li>
})}
</ol>
</Paper>
</Grid>
<Grid item xs={12} sm={9} md={9} lg={9}>
<Paper>
<ol style={{ listStyle: `none` }}>
{posts.map(post => {
const hasVideoUrl = post.video.videoSource
if (hasVideoUrl !== null) {
return (
<li key={post.uri}>
<article
className="post-list-item"
itemScope
itemType="http://schema.org/Article"
>
<header>
<small>{post.video.videoSource}</small>
<small>{post.video.videoUrl}</small>
{/* <ReactPlayer url={post.video.videoUrl} /> */}
</header>
</article>
</li>
)
} else {
return null
}
})}
</ol>
</Paper>
</Grid>
</Grid>
{previousPagePath && (
<>
<Link to={previousPagePath}>Previous page</Link>
<br />
</>
)}
{nextPagePath && <Link to={nextPagePath}>Next page</Link>}
</Layout>
)
}
export default BlogIndex
export const pageQuery = graphql`
query WordPressPostArchive($offset: Int!, $postsPerPage: Int!) {
allWpPost(
sort: { fields: [date], order: DESC }
limit: $postsPerPage
skip: $offset
) {
nodes {
excerpt
uri
date(formatString: "MMMM DD, YYYY")
title
video {
videoSource
videoUrl
}
categories {
nodes {
name
}
}
}
}
}
`
Problem 2 [Added 2 July 2022]:
<ul>
{wpPosts.map(wpPost => {
wpPost.tags.nodes.map(tag => {
console.log(tag.name)
if (tag.name === "Blog") {
return (
<div>
<li>{tag.title}</li>
</div>
)
}
})
})}
</ul>
const data = useStaticQuery(
graphql`
query {
allWpPost(sort: { fields: date, order: DESC }, limit: 10) {
nodes {
excerpt
slug
uri
video {
videoTitle
videoUrl
}
title
date(formatString: "MMMM DD, YYYY")
tags {
nodes {
name
}
}
}
}
}
`
)
const wpPosts = data.allWpPost.nodes
Problem 1: Why i can't return/access the {post1.categories.nodes.name}
? It shows nothing on my page.
nodes (in post1.categories.nodes.name) is likely to be an array, so you will need to loop through it or access a specific position:
return <li>{post1.categories.nodes[0].name}</li>
Depending on your data structure you'll need to loop or just access to the first position. Without knowing your data it's difficult to guess.

How could I preview an image without storing in aws s3?

My question is: Should I create 2 folders: one for temporary and another one for original? I'm using a component for uploading images. When I upload an image, It is stored in s3 and it is retrieved again to be shown in a small image. My problem here is If I upload 1 image and then I decide to upload another one, I uploaded 2 files in the S3 bucket and so on ... without pressing add category.
Finally: I'm using Vue 2 and Laravel 7.x, thanks.
I'm not so familiar with storing process but I need help to decide what is more efficient, thanks.
category.vue
<template>
<Modal v-model="addModal" :closable="false" :mask-closable="false" title="Add a category">
<Input v-model="data.categoryName" placeholder="Add category..."/>
<div class="space"></div>
<Upload ref="uploads" action="/app/upload" :format="['jpg','jpeg','png']" :
headers="{'x-csrf-token': token, 'X-Requested-With': 'XMLHttpRequest'}" :max-size="2048"
:on-error="handleError" :on-exceeded-size="handleMaxSize" :on-format-error="handleFormatError"
:on-success="handleSuccess" type="drag">
<div style="padding: 20px 0">
<Icon size="52" style="color: #3399ff" type="ios-cloud-upload"></Icon>
<p> Click or drag files here to upload </p>
</div>
</Upload>
<div v-if="data.iconImage" class="demo-upload-list">
<img :src="`${data.iconImage}`"/>
<div class="demo-upload-list-cover">
<Icon type="ios-trash-outline" #click="deleteImage"></Icon>
</div>
</div>
<div slot="footer">
<Button type="default" #click="addModal=false">Close</Button>
<Button :disabled="isAdding" :loading="isAdding" type="primary" #click="addCategory">
{{ isAdding ? 'Adding ..' : 'Add a category' }}
</Button>
</div>
</Modal>
</template>
<script>
// Other parts of this section are removed for clarity
export default {
methods: {
async addCategory() {
console.log('1', this.data.iconImage)
if (this.data.categoryName.trim() === '') return this.e('This Category is required')
if (this.data.iconImage.trim() === '') return this.e('This Icon Image is required')
this.data.iconImage = `${this.data.iconImage}`
console.log('2', this.data.iconImage)
const res = await this.callApi('post', 'app/create_category', this.data)
if (res.status === 200) {
this.categoryLists.unshift(res.data)
this.s('Category has been succesfully')
this.addModal = false
this.data.categoryName = ''
this.data.iconImage = ''
this.$refs.uploads.clearFiles()
} else {
if (res.status === 422) {
if (res.data.errors.categoryName) {
this.e(res.data.errors.categoryName[0])
}
if (res.data.errors.iconImage) {
this.e(res.data.errors.iconImage[0])
}
} else {
this.swr()
}
}
},
},
}
</script>
My controller for addCategory
public function addCategory(Request $request)
{
$this->validate($request, [
'categoryName' => 'required',
'iconImage' => 'required',
]);
$category = new Category();
$category->categoryName = $request->categoryName;
$category->iconImage = $request->iconImage;
$category->save();
return response()->json($category);
}

Querying all images in a specific folder using gatsbyjs GraphQL

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

React TypeError: orders.map is not a function

I'm a begginer in React. I'm trying to fetch an array of data about orders and that is working and then map it to display specific information about each order.
I'm getting TypeError: orders.map is not a function exception in my application.
Here's my code:
class Orders extends Component {
state = {
orders: []
};
componentDidMount() {
axios
.get("https://localhost:9090/orders")
.then(res => {
this.setState({ orders: res.data });
console.log(res.data);
});
}
render() {
const { orders } = this.state;
const orderList =
this.state.orders.length > 0 ? (
orders.map(o => {
return (
<div key={o.orderId}>
<p>
{o.isbn}
</p>
</div>
);
})
) : (
<div className="row p-5 m-5">
<div className="offset-sm-5 col-sm-2 text-center">
<span className="text-grey r">Loading...</span>
</div>
</div>
);
return <div className="container">{orderList}</div>;
}}
What's interesting, I have a similar code, that is working. The only difference is basically what it's fetching. Here's the code:
class BookList extends Component {
state = {
books: []
};
componentDidMount() {
console.log(this.props.match.params.search_term);
axios
.get("https://localhost:8080/search?searchTerm=" + search_term)
.then(res => {
this.setState({ books: res.data });
console.log(res.data);
});
}
render() {
const { books } = this.state;
const booksList =
this.state.books.length > 0 ? (
books.map(b => {
return (
<div key={b.isbn} className="card">
<div className="card-body">
<h5 className="card-title">
<Link to={"/details/" + b.isbn}>{b.title}</Link>
</h5>
<div className="card-subtitle text-muted">
{b.author} ({b.year}) /{" "}
<span className=" text-danger">{b.category}</span>
</div>
<p />
</div>
</div>
);
})
) : (
<div className="row p-5 m-5">
<div className="offset-sm-5 col-sm-2 text-center">
<span className="text-grey r">Loading...</span>
</div>
</div>
);
return <div className="container">{booksList}</div>;
}}
I can't find the difference that would cause that exception. It is an array in both cases.
Any suggestions?
EDIT:
here's the output of response data:
response data of order
response data of bokstore
From them images it looks like the orders are processed as plain text and not parsed to JSON. Check that your back-end specifies the required headers Content-Type: application/json so that axios will parse the data correctly.
Alternatively you could parse the text client-side with JSON.parse(res.data)

React Set Image Props

Hello guys im new to REACT im trying to pass my image props to {logo} has anybody a clue how i can set it up ?
123 is displayed but i still miss the image
export default class StickyHeader extends React.Component {
static propTypes = {
}
static defaultProps = {
}
render() {
const { logo } = this.props;
return (
<header>
<div className={'logo'}>
{logo}
</div>
<div>123</div>
</header>
);
}
}
<StickyHeader logo={ <img src="http://via.placeholder.com/350x150" alt="" /> }></StickyHeader>
In this case, I would put the image tag inside your sticky header component, and then pass just the logo url as a property, so your render method would look more like this:
render() {
const { logoUrl } = this.props;
return (
<header>
<div className={'logo'}>
<img src={logoUrl} />
</div>
<div>123</div>
</header>
);
}
}
and then your usage -
<StickyHeader logoUrl={'http://via.placeholder.com/350x150'} />

Resources