React Instant Search recover right data in function - reactjs

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 ?

Related

why link doesn't work when I use getStaticProps?

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.

How to pass props to a component on clicking button?

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;

Fetch tinymce editor content from database in reactjs frontend

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

REACT : empty render despite no errors

I am using the Context API to manage state in a small app. I get the response OK, the Consumer has it, so I map through it and want to pass down data from it to a Product Card component through props. And the Product Card renders absolutely nothing. I get no errors whatsoever. Can anyone help me out please? Here is the code of parent component:
import Pagination from "./Pagination";
import { Consumer } from "../context";
export default class Browse extends Component {
render() {
return (
<Consumer>
{value => {
const { search } = value;
return (
<ProductsGrid>
{search.map(beer => (
<ProductCard
key={beer.id}
beerId={beer.id}
beerName={beer.name}
beerTagline={beer.tagline}
beerAbv={beer.abv}
firstBrewed={beer.first_brewed}
imageUrl={beer.image_url}
/>
))}
</ProductsGrid>
);
}}
</Consumer>
);
}
}`````
and here is the Product Card component:
```export default class ProductCard extends React.Component {
render() {
return (
<div className="product-card">
<div className="product-card-inner">
<div className="product-info-container">
<h1 className="beer-name">{this.props.beerName}</h1>
<p className="beer-type">{this.props.beerTagline}</p>
<p className="beer-alcohol">{this.props.beerAbv}%</p>
<p className="first-brewed">
First brewed: {this.props.firstBrewed}
</p>
</div>
<div className="beer-image-container">
<img src={this.props.imageUrl} alt="beer" />
</div>
<div className="price-container">
<h1>£ 3.50</h1>
</div>
<div className="button-container">
<div className="quantity-container">
<p className="minus-sign"> - </p>
<p className="qty-number"> 0 </p>
<p className="plus-sign"> + </p>
</div>
<div className="add-container">
<IoIosCart />
<p>Add</p>
</div>
</div>
</div>
</div>
);
}
}```

How to scroll to id after clicking on the internal Link in Gatsby.js

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>
...

Resources