Adding items to cart in react js - reactjs

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)
}
}

Related

Unable to load pdf in react

I'm trying to load a pdf file for the user in another tab once they click a button but it's not working and I'm not sure how to make it work. Could I have some help in doing this?
I defined a function PdfViewer() and I call it when a button is clicked using onClick(), but once the button is clicked I get this error:
Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
Here's my code:
import "../styles/ProjectDetails.css";
import React, { useState } from 'react'
import { Document, Page } from 'react-pdf/dist/esm/entry.webpack'
function PdfViewer() {
const [numPage, setNumPages] = useState(null);
const [pageNumber, setPageNumber] = useState(1);
function onDocumentLoadSuccess({numPages}) {
setNumPages(numPage);
setPageNumber(1);
}
return (
<div>
<header>
<Document file="../pdfs/Mini_Case_Study_15.pdf" onLoadSuccess={onDocumentLoadSuccess}>
<Page height="600" pageNumber={pageNumber}></Page>
</Document>
</header>
</div>
)
}
const ProjectDetails = ({ project }) => {
return (
<div className="card-grid">
<div className="card">
<div className="card-header card-image">
<img src="https://c4.wallpaperflare.com/wallpaper/672/357/220/road-background-color-hd-wallpaper-thumb.jpg"/>
</div>
<div className="card-title"><strong>{project.sdg}</strong></div>
<div className="card-body">
<strong>Goal:</strong> {project.goal}
</div>
<div className="card-themes">
<strong>Themes:</strong> {project.theme.map((theme)=>{return theme + ', '})}
</div>
<div className="card-assignment">
<strong>Assignment Type:</strong> {project.assignment_type}
</div>
<div className="card-footer">
<button className="btn">Details</button>
{project.assignment_type === 'Mini Case Studies' &&
<>
<button className="btn btn-outline">Download</button>
{/* <button onClick={PdfViewer} className="btn">Preview</button> */}
</>
}
</div>
</div>
</div>
)
}
export default ProjectDetails
How do I make it so that once the user clicks the button, it takes them to another page with the pdf file shown?
You could try this approach here, inserting the Preview as a Component.
const ProjectDetails = ({ project }) => {
const [preview, setPreview] = useState(false)
const onClickToPreviewPDF = () => {
setPreview(preview ? false : true);
}
return (
<>
<div className="card-grid">
<div className="card">
<div className="card-header card-image">
<img src="https://c4.wallpaperflare.com/wallpaper/672/357/220/road-background-color-hd-wallpaper-thumb.jpg"/>
</div>
<div className="card-title"><strong>{project.sdg}</strong></div>
<div className="card-body">
<strong>Goal:</strong> {project.goal}
</div>
<div className="card-themes">
<strong>Themes:</strong> {project.theme.map((theme)=>{return theme + ', '})}
</div>
<div className="card-assignment">
<strong>Assignment Type:</strong> {project.assignment_type}
</div>
<div className="card-footer">
<button className="btn">Details</button>
{project.assignment_type === 'Mini Case Studies' &&
<>
<button className="btn btn-outline">Download</button>
<button onClick={onClickToPreviewPDF} className="btn">Preview</button>
</>
}
</div>
</div>
</div>
{preview && <PdfViewer />}
</>
)
}

Link same page with different parameters react using link

I want refresh page and send data using link but it don't work
I am using a link to send me to same page but with different parameters but it is not work and it is not refresh ... what I should do?
When I click the link it change from link but it is not change in the page and does not refresh with the data does not change. What should I do?
<Link to={`/NewDetails/${news[arr].id}`}> read more </Link>
the js I'm using is
const NewDetails = () => {
const { id } = useParams();
const [newsDetail, setNewsDetail] = useState("");
useEffect(() => {
async function fetchMyAPI() {
let news = await onGetNewsById(id);
setNewsDetail(news);
}
fetchMyAPI();
}, []);
const [news, setNews] = useState("");
useEffect(() => {
async function fetchMyAPI() {
let news = await onGetNews();
setNews(news);
}
fetchMyAPI();
}, []);
const last_num = news.length;
const last_3_num = news.length - 3;
return (
<div>
<div>
<NavBar />
</div>
<div className="row">
<div className="NewsDetails_Section">
<div className="text-center">
<div className="imageDetailsBackground">
<img className="ImageNewsDetails" src={Wallet} alt="bankimage" />
</div>
</div>
<div className="text-center" dir='rtl'>
<h1> {newsDetail.title} </h1>
</div>
<div className="Body_news_Details">
<p className="text-center"> {newsDetail.content} </p>
</div>
<div>
<div className="News_Details_" dir="rtl">
{Object.keys(news.slice(last_3_num, last_num), NewsImage.slice(last_3_num, last_num)).map(arr => (
<div className="NewSection_details" key={news[arr].id}>
<div className="ImageNews_Details">
<img className="ImageNews_Details" src={NewsImage[arr]} alt="bankimage" />
</div>
<div className="HeaderNews_Details">
<h4>{news[arr].title} </h4>
</div>
<div className="bodynews_details">
<p> {news[arr].content.slice(0, 100)}... </p>
</div>
<div className="ButtonNews_Details">
{/*
<Link Redirect push to={`/NewDetails/${news[arr].id}`}> */}
<Link to={`/NewDetails/${news[arr].id}`}> read more</Link>
</div>
</div>))}
</div>
</div>
</div>
</div>
</div>
);
}

React Owl Carousel 2.3.3 - I loose dynamic data after refreshing page. Working fine on local data

I am using json-server and fetching data using fetch. First time I get data properly in an Owl Carousel and the slider works fine but after when I refresh the page all my dynamic data wipe out. Still my carousel slides but with no data. Also I have attached a jquery script https://code.jquery.com/jquery-3.2.1.slim.min.js in index.html.
I am loosing my Owl Carousel Dynamic Data which I am using through map method in the Owl Carousel Component. Below is the code where I am using my slider. Please help me to find where I am doing wrong. Thank You.
---------------
<<<<<- Below code is MainSlider.js ->>>>>
import React, { useReducer, useEffect } from "react";
import OwlCarousel from "react-owl-carousel";
import "owl.carousel/dist/assets/owl.carousel.css";
import { mainSliderReducer } from "../reducers/mainSliderReducer";
const API = "http://localhost:8000/mainSlider";
const initialState = {};
const MainSlider = () => {
const [state, dispatch] = useReducer(mainSliderReducer, initialState);
const { data } = state;
useEffect(() => {
getData();
}, []);
const getData = () => {
fetch(API)
.then((res) => {
if (res.ok) {
return res.json();
} else {
console.log("DATA NOT FOUND. SOME ERROR");
throw new Error("ERROR FETCHING DATA");
}
})
.then((data) => dispatch({ type: "GET_MAINSLIDER_DATA", payload: data }))
.catch((err) => console.log(err));
};
console.log(data);
return (
<>
<OwlCarousel className="owl-theme" loop margin={10} nav>
{data ? (
data.map((item) => {
const { id, heading, description, img, smallHeading } = item;
return (
<section key={id} className="dvMainSlider">
<div className="item bg bgcolor1 pb-md-5 pt-md-4 py-xl-0 h-100vh h-sm-auto h-xl-100vh">
<div className="container">
<div className="row slideInfo h-xl-100vh align-items-xl-center">
<div className="col-md-6 text-center">
<img
src={img}
className="img-fluid d-inline-block"
alt=""
/>
</div>
<div className="col-md-6 pt-lg-5 pt-xl-0 description">
<h1 className="text-white">{heading}</h1>
<h4 className="text-white">{smallHeading}</h4>
<p className="text-white">{description}</p>
<a href="--" className="btn btnPrimary mb-3 mt-sm-3">
Shop More
</a>
</div>
</div>
</div>
</div>
</section>
);
})
) : (
<h1>"SLIDE NOT FOUND"</h1>
)}
</OwlCarousel>
</>
);
};
export default MainSlider;
<<<<<- Below code is mainSliderReducer.js ->>>>>
export const mainSliderReducer = (state, action) => {
console.log(state, action);
switch (action.type) {
case "GET_MAINSLIDER_DATA":
return { ...state, data: action.payload };
default:
return state;
}
};
Hey I found my own question's answer and i found the way which i am sharing to you all. Just check if data is available then only you load the Owl Carousel Component. Check the code below for better understanding.
{data && (
<OwlCarousel {...options}>
{data.map((item) => {
const { id, heading, description, img, smallHeading } = item;
return (
<section key={id} className="dvMainSlider">
<div className="item bg bgcolor1 pb-md-5 pt-md-4 py-xl-0 h-100vh h-sm-auto h-xl-100vh">
<div className="container">
<div className="row slideInfo h-xl-100vh align-items-xl-center">
<div className="col-md-6 text-center">
<img
src={img}
className="img-fluid d-inline-block"
alt=""
/>
</div>
<div className="col-md-6 pt-lg-5 pt-xl-0 description">
<h1 className="text-white">{heading}</h1>
<h4 className="text-white">{smallHeading}</h4>
<p className="text-white">{description}</p>
<a href="--" className="btn btnPrimary mb-3 mt-sm-3">
Shop More
</a>
</div>
</div>
</div>
</div>
</section>
);
})}
</OwlCarousel>
)}

How to display data from firebase single document using React?

Before this, I'm using Snapshot and try to map it. But it failed for a single document. After I read back the documentations from firebase. They recommend using this way for a single document. But I don't know how to make it readable on the site rather than console. I want to send data on the title and essay.
const { id } = useParams()
useEffect(() => {
db.collection("posts").doc(id).get().then(doc => {
const newData = doc.data();
console.log(newData);
});
}, []);
return (
<div className="log">
<article className="log-details">
<div className="author-pic clearfix">
<img src={profile} alt="" />
</div>
<div className="log-preview">
<div class="cover"></div>
<h2 className="title clearfix">title here</h2>
<div className="details ">
<img src={One} alt="" />
<p className="essay">essay here</p>
</div>
</div>
</article>
</div>
)
To display the post Data use useState and set the postData with setPostData(newData). Then you can read the postData values with {postData.title} and {postData.essay} in the return statement.
Dont forget to import useState with import React, { useState, useEffect } from "react".
const { id } = useParams()
const [postData, setPostData] = useState("");
useEffect(() => {
db.collection("posts").doc(id).get().then(doc => {
const newData = doc.data();
setPostData(newData);
console.log(newData);
});
}, []);
return (
<div className="log">
<article className="log-details">
<div className="author-pic clearfix">
<img src={profile} alt="" />
</div>
<div className="log-preview">
<div class="cover"></div>
<h2 className="title clearfix">{postData && postData.title}</h2>
<div className="details ">
<img src={One} alt="" />
<p className="essay">{postData && postData.essay}</p>
</div>
</div>
</article>
</div>
)

Button Click to Render Div

I want to click the button and render its corresponding div. Should I add the the div's info that I want to render to the state?
I'm sure there's a few different ways to solve this but I want to do it the React way and maybe as a function component?
Updated
export default function About(props) (
const [isHidden, setIsHidden] = useState(true);
const handleClick = () => {
setIsHidden(!isHidden);
};
return (
<div className="row justify-content-md-center">
<div className="col-auto">
<CustomButton onClick={handleClick}>Website Develpment</CustomButton>
</div>
<div className="col-auto">
<CustomButton onClick={handleClick}>Wordpress Develpment</CustomButton>
</div>
<div className="col-auto">
<CustomButton onClick={handleClick}>Ecommerce Development</CustomButton>
</div>
</div>
<div className="row">
<div className="col-md-4">column 1</div>
<div className="col-md-4">column 2</div>
<div className="col-md-4">column 3</div>
</div>
);
)
You can store an ID as a string state variable, and set that variable on button press.
Then use ConditionalRendering to only display the div with the matching ID.
const {useState} = React;
function About(props) {
const [visibleItem, setVisibleItem] = useState('');
return (
<div>
<button onClick={() => setVisibleItem("website")}>
Show Website Develpment
</button>
<button onClick={() => setVisibleItem("wordpress")}>
Show Wordpress Develpment
</button>
<button onClick={() => setVisibleItem("ecommerce")}>
Show Ecommerce Development
</button>
{visibleItem === "website" &&
<div>
<h2>Wordpress Development</h2>
<p>Info about Wordpress and all the things I can do with it</p>
</div>
}
{visibleItem === "wordpress" &&
<div>
<h2>Ecommerce Development</h2>
<p>I can do eccomerce things too</p>
</div>
}
{visibleItem === "ecommerce" &&
<div>
<h2>Website Development</h2>
<p>Info about Webdev</p>
</div>
}
</div>
);
}
ReactDOM.render(
<About/>,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
If the sections were much bigger then I'd recommend splitting them out into separate components, or maybe doing an if or switch statement to select between them before the return, but the above snippet is a pattern I have used often with react.
You can create two states one holding array of button info to minimize repetition of code and another state to track the column clicked.
import React, { useState } from "react";
export default function About(props) {
const [colNum, setColNum] = useState('');
const [btnNames] = useState([
{
colId: 1,
name: "Website Develpment"
},
{
colId: 2,
name: "Wordpress Develpment"
},
{
colId: 3,
name: "Ecommerce Develpment"
}
]);
const handleClick = (id) => {
setColNum(id);
};
return (
<>
<div className="row justify-content-md-center">
{btnNames.map(element => (
<div className="col-auto" key={element.colId}>
<CustomButton onClick={()=> handleClick(element.colId)}>{element.name}</CustomButton>
</div>
))}
</div>
{colNum !== '' ? (<div className="row">
<div className="col-md-4">column {colNum}</div>
</div>) : null }
</>
);
}
So you can define showing value for each section in state, which initial should be false. Then we can handle this state with a function where built-in JS tools can be used (Object.entries, Object.fromEntries and map). The element will be displayed, the value of which will be true, and the rest will automatically become false. More details can be found here: https://codesandbox.io/s/happy-sea-nckmw?file=/src/App.js
import React, { useState } from "react";
import "./styles.css";
import styles from "./TestStyles.module.css";
import CustomButton from "./CustomButton";
export default function App() {
const [showDiv, setShowDiv] = useState({
web: false,
wordpress: false,
ecommerce: false
});
const showDivHandler = (val) => {
const newState = Object.fromEntries(
Object.entries(showDiv).map(([key, value]) => [key, (value = false)])
);
setShowDiv({
...newState,
[val]: !showDiv[val]
});
};
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<div className={styles.Section}>
<div className="col-auto">
<CustomButton clicked={() => showDivHandler("web")}>
Website Develpment
</CustomButton>
</div>
<div className="col-auto">
<CustomButton clicked={() => showDivHandler("wordpress")}>
Wordpress Develpment
</CustomButton>
</div>
<div className="col-auto">
<CustomButton clicked={() => showDivHandler("ecommerce")}>
Ecommerce Development
</CustomButton>
</div>
</div>
<div className={styles.Section} style={{marginTop: 20}}>
{showDiv.web && <div className={styles.Content}>column 1</div>}
{showDiv.wordpress && <div className={styles.Content}>column 2</div>}
{showDiv.ecommerce && <div className={styles.Content}>column 3</div>}
</div>
</div>
);
}
The custom button can look like this:
import React from "react";
const button = (props) => (
<button
onClick={props.clicked}
//some other props if need it(e.g. styles)
>
{props.children}
</button>
);
export default button;
This is how I solved it. Thanks for your help!
export default function About() {
const [visibleItem, setVisibleItem] = useState(1);
const [priceItems] = useState([
{
id: 1,
name: "website",
},
{
id: 2,
name: "wordpress",
},
{
id: 3,
name: "ecommerce",
},
]);
const handleClick = (id) => {
setVisibleItem(id);
};
return (
<div className="container-fluid pricing-wrapper">
<div className="row">
<div className="col">
<h1>Pricing</h1>
</div>
</div>
<div className="row">
<div className="col">
<p>Innovation that empowers your team while also reducing risk!</p>
<div className="seperator"></div>
</div>
</div>
<div className="row justify-content-md-center">
<div className="row justify-content-md-center">
{priceItems.map((item) => (
<div className="col-auto">
<CustomButton onClick={() => setVisibleItem(item.id)}>
{item.name}
</CustomButton>
</div>
))}
</div>
</div>
{priceItems
.filter((item) => item.id === visibleItem)
.map((item) => (
<PriceItem item={item} />
))}
</div>
);
}

Resources