I'm trying to style my blogs page for my website. I integrated my Contentful blog using API's and its all displayed correctly, but I just don't know how to target individual elements to style them individually. I would like to be able to style my main blogs page as a grid layout, attached is the specific grid layout I would like to achieve. I just don't know the code syntax to achieve this. I've been told I need to target the index and use .map but I'm still quite confused
[![the grid layout I want to achieve ][1]][1]
I would also like to be able to add tags to fetch the tags from my Contentful and display them on my blogs main page and on the individual slugs page but I dont know the syntax to fetch this data
import Footer from "../components/Footer/Footer";
import { createClient } from "contentful";
import BlogCard from "../components/BlogCard/BlogCard";
export async function getStaticProps() {
const array = [1, 4, 9, 16];
const map = array.map((x) => x * 2);
const client = createClient({
space: process.env.CONTENTFUL_SPACE_ID,
accessToken: process.env.CONTENTFUL_ACCESS_TOKEN,
previewacessToken: process.env.PREVIEW_ACCESS_TOKEN,
});
const res = await client.getEntries({ content_type: "menuItem" });
return {
props: {
blog: res.items,
},
};
}
export default function Blog({ blog }) {
return (
<div>
<div className="bg-[#F5f5f5] pt-16 max-md:pt-10 max-lg:pt-4">
<div className="flex flex-col">
<header className="z-10">
<Navbar />{" "}
</header>
<main className="flex-1">
<div className="relative left-1/2 mt-12 min-w[100vw] translate-x-[-50%]">
<div className="relative mx-auto pb-30 lg:pb-30">
<div className="px-8 md:px-8.5 lg:px-40">
<div className="mx-auto max-w-container">
<div className="max-md:w-full">
<div className="grid grid-cols-2 grid-rows-3 gap-10 mt-24 mb-32 h-full sm:grid-cols-2 sm:h-full sm:w-full md:mb-24 md:w-full max-lg:block max-md:mt-16 max-md:mb-4">
{/* {blog.map((index) => (
<BlogCard key={index} menuItem={index} />
))} */}
{/* {blog.map((menuItem) => (
<BlogCard key={menuItem.sys.id} menuItem={menuItem} />
))} */}
{blog.map((menuItem) => (
<BlogCard key={menuItem.sys.id} menuItem={menuItem} />
))}
</div>
</div>
</div>
<Footer />
</div>
</div>
</div>
</main>
</div>
</div>
</div>
);````
[1]: https://i.stack.imgur.com/YzU1P.png
Related
I'm new in next js and I'm working on project using NextJS. I have some lots in my items page that shows lots currently(pagination/items.tsx) and I also have lotDetails page that I want it to show details of each lot using dynamic route(lotDetails\id\index.tsx).
This is the folder structure:
Now when I click the Link in Items.tsx I expect it to go to lotDetails page and pass the props, but nothing happens! (It stays on Items page!). here is Items.tsx:
import React from 'react'
import Link from "next/link"
const Items = ({currentItems}:{currentItems:any}) => {
console.log(currentItems)
// const ids=currentItems.map((el:any)=>el.id)
// const paths=ids.map((el:any)=>{params:{id:el.toString()}})
// console.log(paths)
return (
<>
<div className="container">
<div className="row">
{currentItems.map((el:any)=><div className="col-md-3 ">
//this should be linked to lotDetails page!
<Link href={{pathname:"../lotDetails/[id]",query:{id:JSON.stringify(el.id),title:el.title,image:el.image,description:el.description.toString(),rate:el.rating.rate,count:el.rating.count,price:el.price},}} as={`/lotDetails/${el.id.toString()}`}>
<div className="lot">
<div className="img-container">
<img src={el.image}/>
</div>
<div className="title">
{el.title}
</div>
<div className="price">
<span className="price-title">Price:</span>
<span>{el.price}</span>
</div>
</div>
</Link>
</div>)}
</div>
</div>
</>
)
}
export default Items;
I'm using getStaticProps and GetStaticPaths in lotDetails:
const LotDetails = (props:any) => {
const dispatch=useDispatch();
console.log(props)
const lotCount=1;
const addLots=()=>{
dispatch(AddCustomerLot({...props,lotCount:lotCount}))
}
return (
<>
<div className='container lot-details'>
<div className="row" >
<div className="col-md-6">
<div className="detail-container">
<div className="title-details"><h3>{props.title}</h3></div>
<div className="badge"><FontAwesomeIcon icon={faStar}/><span>{props.rate}</span></div>
<div className="inventory">
Inventory: <span className="count">{props.count}</span>
</div>
<div className="description-details">{props.description}</div>
<div className="price">Price: <span className="price-number">{props.price}$</span> </div>
<button className="btn btn-regist" onClick={addLots}>Add to shopping basket</button>
</div>
</div>
<div className="col-md-6"><img src={props.image} alt="" /></div>
</div>
</div>
</>
)
}
export const getStaticPaths:GetStaticPaths=async(context:any)=>{
const response= await axios.get("https://fakestoreapi.com/products")
const paths=response.data.map((el:any)=>({params:{id:el.id.toString()}}))
console.log(paths)
return{
paths,
fallback:'blocking'
}
}
export const getStaticProps:GetStaticProps=async(context:any)=>{
return{
props:
{
//recieve props
id:context.query.id,
title:context.query.title,
image:context.query.image,
description:context.query.description,
rate:context.query.rate,
count:context.query.count,
price:context.query.price
}
}
}
export default LotDetails;
when I deleted getStaticProps and getStaticPaths, the link worked! So I receive that link works perfectly and the problem is in getStaticProps and getStaticPaths. Of course I don't want to use getServerSideProps.
Update
According to julio's suggestion I changed pathName, and I also changed context.query to context.params.id:
Items:
<Link href={{pathname:`/lotDetails/${el.id}`,query:{id:JSON.stringify(el.id),title:el.title,image:el.image,description:el.description.toString(),rate:el.rating.rate,count:el.rating.count,price:el.price},}} as={`/lotDetails/${el.id.toString()}`}>
<div className="lot">
<div className="img-container">
<img src={el.image}/>
</div>
<div className="title">
{el.title}
</div>
<div className="price">
<span className="price-title">Price:</span>
<span>{el.price}</span>
</div>
</div>
</Link>
lotDetails:
return (
<>
<div className='container lot-details'>
<div className="row" >
<div className="col-md-6">
//I removed all section which used props and querys using comments
{/* <div className="detail-container">
<div className="title-details"><h3>{props.title}</h3></div>
<div className="badge"><FontAwesomeIcon icon={faStar}/><span>{props.rate}</span></div>
<div className="inventory">
Inventory: <span className="count">{props.count}</span>
</div>
<div className="description-details">{props.description}</div>
<div className="price">Price: <span className="price-number">{props.price}$</span> </div>
<button className="btn btn-regist" onClick={addLots}>Add to shopping basket</button>
</div> */}
</div>
{/* <div className="col-md-6"><img src={props.image} alt="" /></div> */}
</div>
</div>
</>
)
}
export const getStaticPaths:GetStaticPaths=async(context:any)=>{
const response= await axios.get("https://fakestoreapi.com/products")
const paths=response.data.map((el:any)=>({params:{id:el.id.toString()}}))
console.log(paths)
return{
paths,
fallback:'blocking'
}
}
export const getStaticProps:GetStaticProps=async(context:any)=>{
return{
props:
{
id:context.params.id,
// title:context.query.title,
// image:context.query.image,
// description:context.query.description,
// rate:context.query.rate,
// count:context.query.count,
// price:context.query.price
}
}
}
Finally, I solved problem in two steps:
1-I'm using google chrome browser, so I configured chrome and added my localhost port:
I used this link: chrome://inspect/, clicked configure button and added my localhost port(in my case localhost:3000)
2-I added this code to lotDetails page(the page which I used axios)
axios.defaults.httpsAgent=new https.Agent({
rejectUnauthorized:false,
})
don't forget to import:
import https from "https"
Now It's working.
I am using Next Js (React Js) to develop my Web app here, I have also used graphql to get my data from database I am also getting it but not able to render it on screen. What should I do!
import Link from 'next/link'
import moment from 'moment'
import {getRecentPosts , getSimilarPosts} from '../../services'
const PostWidget = ({categories , slug}) => {
const [relatedPosts, setRelatedPosts] = useState([])
useEffect(() => {
if(slug){
getSimilarPosts(categories, slug).then((result) => setRelatedPosts(result))
}
else{
getRecentPosts().then((result) => setRelatedPosts(result))
}
}, [slug])
return (
<div>
<h3>
{slug ? "Related Posts" : "Recent Posts"}
</h3>
{relatedPosts.map((post) =>{
<div key={post.slug}>
<div className="image">
<img
src={post.featuredImage.url}
alt="" />
</div>
<div className="content">
<p>{moment(post.createdAt).format('MMM DD, YYYY')}</p>
<h3>{post.title.toString()}</h3>
</div>
</div>
})}
</div>
)
}
export default PostWidget
When I console.log(relatedPosts) this I am able to get the data in json format but when I try to use it like above I am not getting the post information and am not able to show my data in my web page
{relatedPosts.map((post) => (
<div key={post.slug}>
<div className="image">
<img
src={post.featuredImage.url}
alt=""
/>
</div>
<div className="content">
<p>{moment(post.createdAt).format('MMM DD, YYYY')}</p>
<h3>{post.title}</h3>
</div>
</div>
))}
Because I inserted a {curly bracket} instead of a (paranthesis):
(post)=>{ code/JSX } ❌
We can correct this in two ways :
(post)=>{ return ( code/JSX )} ✔
or
(post)=>( code/ JSX(react/next) ) ✔
Currently building my portfolio site using Next.js and Sanity for my CMS. I've managed to pull the featured image for a project using the useEffect and setImageUrl method. I'm trying to pull images to display on the front end for different sections on the project details page. These are images I uploaded to my database through sanity. I end up getting the broken image icon instead of the actual image. I'm pretty stumped on why it's not pulling the image data correctly. Here is the code for the project single page (as a slug).
import imageUrlBuilder from '#sanity/image-url'
import { useState, useEffect } from 'react';
import BlockContent from '#sanity/block-content-to-react'
export const Post = ({ title, image, problem, solution, role, body, body2, body3, body4, body5, photo }) => {
const [imageURL, setImageUrl] = useState('');
useEffect(() => {
const imgBuilder = imageUrlBuilder({
projectId: 'hidden',
dataset: 'production',
});
setImageUrl(imgBuilder.image(image));
}, [image]);
return (
<div>
<div className="container mx-auto mt-8 mb-20 px-6">
{imageURL && <img className="my-8" src={imageURL} />}
<h1 className="text-5xl font-bold my-8">{title}</h1>
<div className="flex justify-between space-x-12 mb-8">
<div className="flex flex-col">
<h3 className="text-lg font-semibold">The Problem</h3>
<div className="w-auto my-2">
<BlockContent blocks={problem} />
</div>
</div>
<div className="flex flex-col">
<h3 className="text-lg font-semibold">The Solution</h3>
<div className="w-auto my-2">
<BlockContent blocks={solution} />
</div>
</div>
<div className="flex flex-col">
<h3 className="text-lg font-semibold">Role</h3>
<div className="w-auto my-2">
<BlockContent blocks={role} />
</div>
</div>
</div>
<img src={photo} />
<div className="w-auto">
<BlockContent blocks={body} />
</div>
<div className="w-auto">
<BlockContent blocks={body2} />
</div>
<div className="w-auto">
<BlockContent blocks={body3} />
</div>
<div className="w-auto">
<BlockContent blocks={body4} />
</div>
<div className="w-auto">
<BlockContent blocks={body5} />
</div>
</div>
)
};
export const getServerSideProps = async pageContext => {
const pageSlug = pageContext.query.slug;
if (!pageSlug) {
return {
notfound: true
}
}
const query = encodeURIComponent(`*[ _type == "project" && slug.current == "${pageSlug}"]`) ;
const url = `https://hidden?query=${query}`;
const result = await fetch(url).then(res=> res.json());
const post = result.result[0];
if(!post) {
return{
notfound: true
}
} else {
return {
props: {
title: post.projectTitle,
image: post.projectImage,
problem: post.problem,
solution: post.solution,
role: post.role,
body: post.sectionOne,
body2: post.sectionTwo,
body3: post.sectionThree,
body4: post.sectionFour,
body5: post.sectionFive,
photo: post.Image01
}
}
}
};
export default Post;
instead of using a deconstructor for your imageUrl, try with the following syntax:
import sanityClient from "../../lib/client";
import imageUrlBuilder from "#sanity/image-url";
const builder = imageUrlBuilder(sanityClient);
function urlFor(source) {
return builder.image(source);
}
{item.image && (<img src={urlFor(item.image).width(220).url()} alt={item.title} />)}
where sanityClient.js in React:
https://www.sanity.io/guides/create-a-single-page-application-with-react-and-sanity
and in Next.js:
https://www.sanity.io/guides/sanity-nextjs-tailwindcss
I am developing a web application using MERN stack. I am using Redux Toolkit for state management.
I display a list of blog posts on the homepage.
When I click on the view button, I am taken to the page for that particular post.
However, when I refresh the page, I no longer see the post.
Why it it happening?
The following are my code snippets:
src/components/ViewPost.js
import React from "react";
import { useSelector } from "react-redux";
const ViewPost = ({ match }) => {
const post = useSelector((state) =>
state.posts.posts.find((post) => post._id === match.params.id)
);
return (
<div>
{post ? (
<div className="row mt-5">
<div className="col-md-8 mx-auto">
<article>
<h3 className="">{post.title}</h3>
<h6 className="text-muted mb-3">
by Hemanta Sundaray | {new Date().toISOString().slice(0, 10)}
</h6>
<div className="col mb-3 post-border"></div>
<p>{post.body}</p>
</article>
</div>
</div>
) : (
<h3 className="text-center mt-5">POST NOT FOUND</h3>
)}
</div>
);
};
export default ViewPost;
I built a site with nextjs (with server express & API) and Reactjs.
I would like to create dynamic paginations because there is far too much result for statically generated, So I added server endpoint /publiations/page/:id, I put a getInitialsProps for keep the id in query
But actually, when I click on my main page /publications where my store is not empty to go to the next page (publications/page/1), the page reloads and the store is empty. How I can keep my store when I change route?
And here my publications/page/[id].js
const PublicationsPage = ({id}) => {
return (
<>
<MainMenu/>
<Search/>
<div className="flex">
<Sidebar fallback={<Loader/>}/>
<Cards type={'publications'} idPage={id} />
</div>
</>
)
}
PublicationsPage.getInitialProps = async function({ query: { id } }) {
return {
id: id
};
};
export default withAuthSync(PublicationsPage);
The cards components where i use the data of store :
components/Cards.js
const Cards = ({ idPage, cards, type }) => {
console.log(cards)
return (
<div className="cards">
<div className="content-filter-search">
<div className="content-newsearchresult">
<div className="global-name">Result: {cards.cards.length} articles found</div>
<div className="content-button-blue">
<Link href="/explorer">
<a>
<div className="button-blue">New search</div>
</a>
</Link>
</div>
</div>
<div className="content-filter">
{filters[idPage].map((item) => {
return <InputFilter key={item.id} data={item} callback={keepItems} />;
})}
</div>
</div>
<div className="wrapper-card">
<div className="cards-container">
{
!cards.loading ? cards.cards.slice(idPage * 9, idPage * 9 + 9).map((card) => (
<Card key={card.PMCID} data={card} />
)) : <Spinner color="black" size="100px" thickness={3} gap={5} speed="fast" />
}
</div>
</div>
<div className="text">
<Link href={'/publications/page/1'}><a>Next page</a></Link>
</div>
{
!cards.loading ? (
<div className="center">
<Pagination type={type} page={parseInt(idPage)} totalElement={cards.cards.length} numberPerPage={9} />
</div>
) : null
}
</div>
);
};
const mapStateToProps = state => ({
cards: state.cards,
})
export default connect(mapStateToProps)(Cards);
I use the same code for the route /publications and /publications/page/:id just I add the getInitialProps to keep the id of page. And I use connect redux in my Cards component
I have no error in the console just my store is reset because the page reload. I don't understand how I can make pagination with my store where is my data if when I change page the store is empty
Thanks