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.
Related
In reactjs, what code would I have to write in my two components(homepage.js with an add-to-cart button and a checkout page with a clear cart button? This is my Homepage.js where I fetch the items from my backend server, map, and display them on the page.
function Home() {
const [data, setData] = useState([]);
useEffect(() => {
// auto-login
fetch("/coffees").then((res) => {
if (res.ok) {
res.json().then((data) => setData(data))
}
});
}, [])
console.log(data)
return (
<>
<div className="box">
<div className="projo">
<h2 >Welcome to Coffee-cafe</h2>
</div>
<div className="projects">
{data.map((data) =>{
return(
<div className="card">
<img className="avatar" src={data.coffee_image} alt="coffee"></img>
<div className="card-content">
<h4><b>{data.coffee_name}</b></h4>
<p id="desc">{data.description}</p>
<p className="price">{data.price}</p>
{/* <p>{data.category}</p> */}
<button onClick={() => ({})} className="btn1" id="btn1">Add to Cart</button>
</div>
</div>
)
})}
</div>
</div>
</>
)
}
export default Home;
For the Checkout.js, this is what I have currently.
function Checkout() {
return (
<>
<div className="section">
<div className="photo">
<img className="dp" src={image1} alt="coffee"></img>
<div className="info">
<h3>Coffee:</h3>
<p>Price:</p>
<p>Category:</p>
<div className="check-out-btn">
{/* <button className="add">AddToCart</button> */}
<button className="delete">ClearCart</button>
</div>
</div>
</div>
</div>
take a look for a global states like redux , context,or zustand
for my recommendation, I suggest zustand is less code than context and redux and short learning curve
carts =[]
setItemToCart(item){
const isExist = carts.find(c => c.id ===item.id)
if(isExit){
const qty = isExit.qty+item.qty
const newItem= {...item,qty}
// push is not recommended to use because it mutates state
carts.push(newItem)
}else{
carts.push(item)
}
}
I have displayed all the anime images from api, now I want if any anime result is clicked then it should open details for that particular anime. I have created component Details where I want to send details of anime.
how can I send details of anime to the component Details ?
Here is my code:
import { useEffect, useState } from 'react';
import './CSS/style.css';
import Details from './components/Details';
function App() {
const [user, setUser] = useState([])
const getUsers = async () =>{
const response = await fetch('https://ghibliapi.herokuapp.com/films')
setUser(await response.json());
}
useEffect(() => {
getUsers();
}, []);
const getDetail = (e) =>{
// what should I write here to pass props on component < Details />
console.log(e)
}
return (
<>
<h2>Anime World</h2>
<div className="container-fluid mt-5">
<div className="row text-center">
{
user.map((curElem) => {
return (
<div className="col-10 col-md-4 mt-5" key={curElem.id} >
<div className="card">
<img src={curElem.image} className="card-img-top imageSize" alt="..."/>
<div className="card-body">
<h5 className="card-title">{curElem.title} </h5>
<button onClick={getDetail} >Get Detail</button>
</div>
</div>
</div>
)
})
}
</div>
</div>
</>
);
}
export default App;
Dummy values are given to component Details right now, I have to get correct value from props.
import React from 'react';
import './details.css';
function Details() {
return (
<>
<h2>Information of Anime</h2>
<div className="container-fluid mt-5">
<div className="row text-center">
<div className="col-10 col-md-8 mx-auto" >
<div className="card box">
<img src= '...' className="card-img-top imageSize" alt="..."/>
<div className="card-body">
<div className='details'>
<h5><span>Title:</span> Title</h5>
<h5><span>Original Title:</span> Original Title</h5>
<h5><span>Director:</span> Director</h5>
<h5><span>Producer:</span> Producer</h5>
<h5><span>Release Date:</span> date</h5>
<h5><span>Running time:</span> time</h5>
<h5><span>Description:</span> <p> Description</p></h5>
</div>
</div>
</div>
</div>
</div>
</div>
</>
)
}
export default Details;
I'm going to assume that the list you receive from the API is the list of each anime, and when you click you want to render the selected anime using the Details component. If that's the case this is my approach
import { useEffect, useState } from 'react';
import './CSS/style.css';
import Details from './components/Details';
function App() {
const [user, setUser] = useState([]);
const [anime, setAnime] = useState(null);
const getUsers = async () =>{
const response = await fetch('https://ghibliapi.herokuapp.com/films');
setUser(await response.json());
};
useEffect(() => {
getUsers();
}, []);
const getDetail = (anime) =>{
setAnime(anime);
};
return (
<>
<h2>Anime World</h2>
<div className="container-fluid mt-5">
<div className="row text-center">
{user.map((elem) => (
<div className="col-10 col-md-4 mt-5" key={curElem.id}>
<div className="card">
<img src={elem.image} className="card-img-top imageSize" alt="..."/>
<div className="card-body">
<h5 className="card-title">{elem.title} </h5>
<button onClick={() => getDetail(elem)} >Get Detail</button>
</div>
</div>
</div>
))}
</div>
</div>
{anime && <Details {...anime} />}
</>
);
}
export default App;
So basically what I'm doing here is rendering <Details /> only when an anime element is in state. If it's null it won't render the component.
Secondly I'm spreading the selected element into the Details component, so that inside the component you can access each property like this:
import React from 'react';
import './details.css';
function Details(props) {
const { title } = props; // each prop is each property of the selected anime
return (
<>
<h2>Information of Anime</h2>
<div className="container-fluid mt-5">
<div className="row text-center">
<div className="col-10 col-md-8 mx-auto" >
<div className="card box">
<img src= '...' className="card-img-top imageSize" alt="..."/>
<div className="card-body">
<div className='details'>
<h5><span>Title:</span> {title}</h5>
<h5><span>Original Title:</span> Original Title</h5>
<h5><span>Director:</span> Director</h5>
<h5><span>Producer:</span> Producer</h5>
<h5><span>Release Date:</span> date</h5>
<h5><span>Running time:</span> time</h5>
<h5><span>Description:</span> <p> Description</p></h5>
</div>
</div>
</div>
</div>
</div>
</div>
</>
)
}
export default Details;
I create my about page data dynamic using Laravel and reactjs. I need to fetch my TinyMCE editor content from the database in my react js frontend application. It fetches but with an HTML tag. I need to fetch it without an HTML tag. My backend API is in Laravel Please help me.
my component code is
import React, {useState, useEffect} from 'react';
import Menu from './Menu';
import Footer from './Footer';
import {getAboutPage} from "./apiCore";
const About = () => {
const [getAboutContent, setAllAboutContent] = useState([]);
const loadAllAboutContent = () => {
getAboutPage().then(data => {
if(data.error){
console.log(data.error)
} else{
setAllAboutContent(data.data)
console.log(data.data)
}
});
};
useEffect(() =>{
loadAllAboutContent();
}, [])
return(
<div>
<Menu/>
{/* {JSON.stringify(getAboutContent)} */}
{getAboutContent.map((p, i) => (
<div>
<div className="slider_area">
<div className="single_slider about_bg_1 d-flex align-items-center" style={{background: `url(${"http://localhost:8000/storage/uploads/abouts/"+p.banner})`}}>
<div className="container">
<div className="row">
<div className="col-12">
<div className="slider_text">
<h3>{p.banner_text}</h3>
</div>
</div>
</div>
</div>
</div>
</div>
<div className="about_desc">
<div className="container">
<div className="row justify-content-center ">
<div className="col-lg-12 col-md-10">
<div className="section_title text-center">
<h4>{ p.description}</h4>
</div>
</div>
</div>
</div>
</div>
</div>
))}
<Footer/>
</div>
)
}
export default About;
Please guide me.
First solution : You can use
<div
dangerouslySetInnerHTML={{
__html: p.description
}}></div>
Second solution Use react-html-parser
I am building a blog and after clicking on Link linking to an article I want the new page to be scrolled on the Title of the article.
I have tried to use <Link to={`/${node.slug}#blog-title`}>{node.title}</Link>
but it doesn't scroll to title, it scrolls back to top of the page.
I have tried to use window.scrollTo(document.getElementById('blog-title); in componentDidMount but it looks like it's not renered until then and it still goes to top. If I use setTimeout it only scrolls to top to straight away scroll to the correct id.
index.js
return (
<article className="blog-listing" key={node.slug}>
<div className="entry-meta-content">
<h2 className="entry-title">
<Link to={`/${node.slug}`}>{node.title}</Link>
</h2>
<span className="entry-meta">
Created on {node.publishDate} By {node.author.name}
</span>
</div>
<div className="entry-media">
<Img fluid={node.heroImage.fluid} backgroundColor="#f4f8fb" />
</div>
<div className="entry-content-bottom">
<p className="entry-content">{node.body.childMarkdownRemark.excerpt}</p>
<Link to={`/${node.slug}`} className="entry-read-more">
<span />
Read More
</Link>
</div>
</article>
);
blog-post.js
import React, { Component } from 'react';
import get from 'lodash/get';
import Helmet from 'react-helmet';
import { graphql } from 'gatsby';
import Img from 'gatsby-image';
import Template from '../components/layout';
class BlogPostTemplate extends Component {
render() {
const post = get(this, 'props.data.contentfulBlogPost');
return (
<Template>
<Helmet title={`${post.title}`} id="blog-title" />
<div className="inner-blog-post">
<div className="container">
<div className="row">
<div className="col-lg-12 col-md-12">
<div className="entry-media">
<Img fluid={post.heroImage.fluid} backgroundColor="#f4f8fb" />
</div>
<h1 className="section-headline"> {post.title} </h1>
<p> {post.publishDate} </p>
<div
dangerouslySetInnerHTML={{
__html: post.body.childMarkdownRemark.html
}}
/>
</div>
</div>
</div>
</div>
</Template>
);
}
}
export default BlogPostTemplate;
export const pageQuery = graphql`
query blogPostQuery($slug: String) {
contentfulBlogPost(slug: { eq: $slug }) {
title
body {
childMarkdownRemark {
html
}
}
heroImage {
file {
url
}
fluid(maxWidth: 1800) {
...GatsbyContentfulFluid_withWebp_noBase64
}
}
}
}
`;
Thanks!
In your blogpost.js, you're attaching an id to the <Helmet> tag, which doesn't generate any content in the body. Perhaps you should attach it to the title in the body instead?
...
<Template>
- <Helmet title={`${post.title}`} id="blog-title" />
+ <Helmet title={`${post.title}`} />
<div className="inner-blog-post">
<div className="container">
<div className="row">
<div className="col-lg-12 col-md-12">
<div className="entry-media">
<Img fluid={post.heroImage.fluid} backgroundColor="#f4f8fb" />
</div>
- <h1 className="section-headline"> {post.title} </h1>
+ <h1 id="blog-title" className="section-headline"> {post.title} </h1>
...
I work actually in my first React Project for a little startup, an "search and add to your collection" app. For the search feature, i use React Instant Search by Algolia. Everything work find.
Now, for the "add to collection" feature, i know how to do that, but I can not recover the data in my function. I did a little test like this:
import React from 'react';
import withAuthorization from './withAuthorization';
import * as firebase from 'firebase';
import {database, } from '../firebase/firebase';
import Image from 'react-image-resizer';
import{InstantSearch, SearchBox, Hits, Highlight, RefinementList} from "react-instantsearch/dom";
import { orderBy } from "lodash";
function addToCollection({hit}) {
console.log('-----');
console.log('The selected item is:', hit);
console.log('------');
}
const Hit = ({hit}) =>
<div className="hit">
<div className="hit-image">
<img src={hit.avatarURL} height={150} width={150}/>
</div>
<div className="hit-content">
<div className="hit-marque">
{hit.marque}
</div>
<div className="hit-numero">
{hit.numero}
</div>
<div className="hit-marquesuite">
{hit.marquesuite}
</div>
<div className="hit-reference">
{hit.reference}
</div>
<div className="hit-cote">
{hit.cote}
</div>
<button className="btn btn-success" onClick={addToCollection}>Ajouter à ma collection</button>
</div>
</div>
const Content = () =>
<div className="content container-fluid text-center">
<div className="row">
<div className="col-lg">
<Hits hitComponent={Hit} key ={Hit}/>
</div>
</div>
</div>
class Catalogue extends React.Component {
constructor(){
super();
this.state = {
catalogue: {},
};
}
render(){
if(this.state.catalogue === null) {
return <p>Le catalogue est vide</p>
}
return (
<div class="container-fluid">
<h1 className="text-center">Catalogue de capsule</h1>
<h4 className="text-center">Rechercher une capsule</h4>
<InstantSearch
apiKey="a8de2c61b98e1ca62a5df03f1970f46a"
appId="7H3CTF406R"
indexName="catalogue">
<SearchBox translation={{placeholder:'Rechercher une capsule'}} width="500 px"/>
<Content />
</InstantSearch>
</div>
);
}
}
const authCondition = (authUser) => !!authUser;
export default withAuthorization(authCondition)(Catalogue);
So, how can I transmit the information of my const "Hit" to my function "addToCollection" when I click on button.
Thank in advance for your help
<div className="hit-content">
<div className="hit-marque"> {hit.marque} </div>
<div className="hit-numero"> {hit.numero} </div>
<div className="hit-marquesuite"> {hit.marquesuite} </div>
<div className="hit-reference"> {hit.reference} </div>
<div className="hit-cote"> {hit.cote}
</div>
How can you access hit.cote and hit.avatarurl ?