I am using react and globalContext to add items to a cart page and this adds the product to the array stored in localStorage and looks like this.
0: {id: "9", title: "Apple Watch SE 40mm (GPS) - Space Grey Aluminium Case with Midnight Sport Band",…}
id: "9"
price: 249.99
quantity: 1
src: "/static/media/se.0ca02982636517aed223.png"
title: "Apple Watch SE 40mm (GPS) - Space Grey Aluminium Case with Midnight Sport Band"
I have a quantity selector on the page for every item added to the basket which displays the quantity how do i make it so when that quantity is changed the price alters too?
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome'
import { faChevronLeft, faClose, faPlus, faMinus } from '#fortawesome/free-solid-svg-icons'
import React, {useContext, useEffect, useState} from 'react'
import { NavLink } from 'react-router-dom'
import { GlobalContext } from '../context/GlobalState'
export const Basket = () => {
const {basket, removeFromCart} = useContext(GlobalContext)
let cartArray = localStorage.getItem("basket");
cartArray = JSON.parse(cartArray);
const total = cartArray.reduce((prev, cur) => (cur.price * cur.quantity) + prev, 0);
console.log(total)
const [quantity, setQuantity] = useState(0);
const handleReduceQuantity = () => {
if (quantity === 0) return;
setQuantity((prev) => prev - 1);
};
const handleIncreaseQuantity = () => {
setQuantity((prev) => prev + 1);
};
return (
<div className="h-screen bg-zinc-100 p-4">
<div className="py-5">
<div className="max-w-md mx-auto bg-white shadow-lg rounded-lg md:max-w-7xl">
<div className="md:flex">
<div className="w-full p-4">
<div className="md:grid md:grid-cols-3 gap-2 ">
<div className="col-span-2 p2 md:p-5">
<h1 className="text-xl font-bold ">Shopping Basket</h1>
<div className="flex justify-between flex-col items-center mt-6 pt-6 gap-12">
{basket.length > 0 ? (
<>
{basket.map(item => (
<>
<div className='flex flex-col w-full justify-between md:gap-44 items-start'>
<div className="flex items-center">
<img src={item.src} className="rounded w-20 " />
<div className="flex flex-col ml-3 gap-1 ">
<span className="md:text-lg text-sm font-bold w-full md:t-width ">{item.title}</span>
<span className="text-xl font-bold">£ {item.price}</span>
</div>
<div className="flex items-center justify-between py-2 bg-gray-100 rounded-md md:w-36">
<FontAwesomeIcon
icon={ faMinus }
className="ml-4 transform scale-110 cursor-pointer text-primary"
onClick={handleReduceQuantity}
/>
<span className="text-lg font-bold text-secondary-dark">
{item.quantity}
</span>
<FontAwesomeIcon
icon={ faPlus }
className="mr-4 transform scale-110 cursor-pointer text-black"
onClick={handleIncreaseQuantity}
/>
</div>
<FontAwesomeIcon icon={ faClose } onClick={() =>
removeFromCart(item.id)}/>
</div>
</div>
</>
))}
</>
) : (
<div>No Items</div>
)}
</div>
<div className="flex justify-between items-center mt-6 pt-6 border-t">
<NavLink to="/">
<div className="flex items-center"> <i className="fa fa-arrow-left text-sm pr-2"></i>
<span className="text-md font-medium text-amz hover:text-orange-500 cursor-pointer ">
<FontAwesomeIcon icon={ faChevronLeft }></FontAwesomeIcon> Continue Shopping</span>
</div>
</NavLink>
<div className="flex justify-center items-end">
<span className="text-sm font-medium text-gray-400 mr-1">Subtotal:</span>
<span className="text-lg font-bold text-gray-800 ">£ {total}</span>
</div>
</div>
</div>
<div className=" p-5 bg-gray-800 rounded overflow-visible">
<span className="text-xl font-medium text-gray-100 block pb-3">Total</span>
<div className="flex justify-center flex-col pt-3">
<label className="text-xs text-gray-400 ">Name on Card</label>
<input type="text" className="focus:outline-none w-full h-6 bg-gray-800 text-white placeholder-gray-300 text-sm border-b border-gray-600 py-4" placeholder="Giga Tamarashvili"/>
</div>
<div className="flex justify-center flex-col pt-3">
<label className="text-xs text-gray-400 ">Card Number</label>
<input type="text" className="focus:outline-none w-full h-6 bg-gray-800 text-white placeholder-gray-300 text-sm border-b border-gray-600 py-4" placeholder="**** **** **** ****"/>
</div>
<div className="grid grid-cols-3 gap-2 pt-2 mb-3">
<div className="col-span-2 ">
<label className="text-xs text-gray-400">Expiration Date</label>
<div className="grid grid-cols-2 gap-2">
<input type="text" className="focus:outline-none w-full h-6 bg-gray-800 text-white placeholder-gray-300 text-sm border-b border-gray-600 py-4" placeholder="mm"/>
<input type="text" className="focus:outline-none w-full h-6 bg-gray-800 text-white placeholder-gray-300 text-sm border-b border-gray-600 py-4" placeholder="yyyy"/>
</div>
</div>
<div className="">
<label className="text-xs text-gray-400">CVV</label> <input type="text" className="focus:outline-none w-full h-6 bg-gray-800 text-white placeholder-gray-300 text-sm border-b border-gray-600 py-4" placeholder="XXX"/>
</div>
</div>
<button className="h-12 w-full bg-blue-500 rounded focus:outline-none text-white hover:bg-blue-600">Check Out</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
)
}
At the moment the quantity selector is just a counter and doesn't change the quantity of the item in localStorage and therefore doesn't change the total price.
const items = [
{
id: "9",
price: 200,
quantity: 1,
src: "/static/media/se.0ca02982636517aed223.png",
title: "Apple Watch SE 40mm (GPS) - Space Grey Aluminium Case with Midnight Sport Band",
},
{
id: "3",
price: 300,
quantity: 1,
src: "/static/media/se.0ca02982636517aed223.png",
title: "Apple Watch SE 40mm (GPS) - Space Grey Aluminium Case with Midnight Sport Band",
}
];
const calculateTotal = (items) => {
const total = items.reduce((acc, curr) => (curr.price * curr.quantity) + acc, 0);
console.log(total);
}
const handleQuantityUpdate = (itemId, operation) => {
const newItems = items.map((i) => {
if(i.id === itemId){
return {...i, quantity: operation === 'increase' ? i.quantity + 1 : i.quantity - 1};
}
return {...i};
});
//need to store into localstorage at this point
console.log(newItems);
calculateTotal(newItems);
}
handleQuantityUpdate("9", 'increase');
handleQuantityUpdate("3", "decrease");
Related
I have 2 dynamic inputs academic and teaching exp but only academic works
and when I try to add a new field to teachingExp it returns typeError: teachingExp.map is not a
function
i have used the same code for both dynamic inputs but one works and other does not
both these input divs are inside a form
outside component return
const [academic, setAcademic] = useState([
{
degree: "",
branch: "",
university: "",
completionYear: "",
grade: "",
},
]);
const [teachingExp, setTeachingExp] = useState([
{
university: "",
designation: "",
period: "",
},
]);
const handleAcademicChange = (index, e) => {
let data = [...academic];
data[index][e.target.id] = e.target.value;
setAcademic(data);
};
const handleTeachingExpChange = (index, e) => {
let data = [...teachingExp];
data[index][e.target.name] = e.target.value;
setTeachingExp(data);
};
const addAcademic = () => {
let newAcademic = {
degree: "",
branch: "",
university: "",
completionYear: "",
grade: "",
};
setAcademic([...academic, newAcademic]);
};
const addTeachingExp = () => {
let newTeachingExp = {
university: "",
designation: "",
period: "",
};
setTeachingExp(...teachingExp, newTeachingExp);
};
const removeAcademic = (index) => {
let data = [...academic];
data.splice(index, 1);
setAcademic(data);
};
const removeTeachingExp = (index) => {
let data = [...teachingExp];
data.splice(index, 1);
setTeachingExp(data);
};
inside return
<div className="flex justify-center w-full m-auto my-6 p-4 font-sans ">
<div className="flex flex-col p-3">
<h3 className="text-center p-3 text-3xl font-medium text-gray-700 mb-5 ">
Academic Qualifications
</h3>
{academic.map((input, index) => {
return (
<div
key={index}
className="w-56 mb-4 relative group grid place-content-center place-items-center m-auto lg:grid-flow-col gap-4 "
>
<div className="w-56 lg:w-40 p-2 xl:w-56">
<label className="text-sm font-light">Degree/Title</label>
<input
className="form-control
block
w-full
px-3
py-1.5
text-base
font-normal
text-gray-700
bg-white bg-clip-padding
border border-solid border-gray-300
rounded
transition
ease-in-out
m-0
focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none "
type="text"
required
id="degree"
autoComplete="true"
placeholder="Enter degree"
value={input.degree}
onChange={(e) => handleAcademicChange(index, e)}
/>
</div>
<div className="w-56 lg:w-40 p-2 xl:w-56">
<label className="text-sm font-light">
Branch/Specialization
</label>
<input
className="form-control
block
w-full
px-3
py-1.5
text-base
font-normal
text-gray-700
bg-white bg-clip-padding
border border-solid border-gray-300
rounded
transition
ease-in-out
m-0
focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none "
type="text"
required
id="branch"
autoComplete="true"
placeholder="Enter branch"
value={input.branch}
onChange={(e) => handleAcademicChange(index, e)}
/>
</div>
<div className="w-56 lg:w-40 p-2 xl:w-56">
<label className="text-sm font-light">
University/College
</label>
<input
className="form-control
block
w-full
px-3
py-1.5
text-base
font-normal
text-gray-700
bg-white bg-clip-padding
border border-solid border-gray-300
rounded
transition
ease-in-out
m-0
focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none "
type="text"
required
id="university"
autoComplete="true"
placeholder="Enter university"
value={input.university}
onChange={(e) => handleAcademicChange(index, e)}
/>
</div>
<div className="w-56 lg:w-40 p-2 xl:w-56">
<label className="text-sm font-light">
Completion year
</label>
<input
className="form-control
block
w-full
px-3
py-1.5
text-base
font-normal
text-gray-700
bg-white bg-clip-padding
border border-solid border-gray-300
rounded
transition
ease-in-out
m-0
focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none "
type="text"
required
id="completedYear"
autoComplete="true"
placeholder="Enter completion year"
value={input.completedYear}
onChange={(e) => handleAcademicChange(index, e)}
/>
</div>
<div className="w-56 lg:w-40 p-2 xl:w-56">
<label className="text-sm font-light">Grade/Marks</label>
<input
className="form-control
block
w-full
px-3
py-1.5
text-base
font-normal
text-gray-700
bg-white bg-clip-padding
border border-solid border-gray-300
rounded
transition
ease-in-out
m-0
focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none "
type="text"
required
id="grade"
autoComplete="true"
placeholder="Enter grade"
value={input.grade}
onChange={(e) => handleAcademicChange(index, e)}
/>
</div>
{academic.length > 1 ? (
<TrashIcon
className="h-8 mt-5 mx-4 text-red-600"
onClick={() => removeAcademic(index)}
/>
) : (
""
)}
</div>
);
})}
<PlusCircleIcon
className="h-12 p-2 mx-4 text-[#020493] mt-1"
onClick={addAcademic}
/>
</div>
</div>
<div className="flex justify-center w-full m-auto my-6 p-4 font-sans ">
<div className="flex flex-col p-3">
<h3 className="text-center p-3 text-3xl font-medium text-gray-700 mb-5 ">
Teaching Experience
</h3>
{teachingExp.map((input, index) => (
<div
key={index}
className="w-56 mb-4 relative group grid place-content-center place-items-center m-auto lg:grid-flow-col gap-4 "
>
<div className="w-56 lg:w-40 p-2 xl:w-56">
<label className="text-sm font-light">
University/College
</label>
<input
className="form-control
block
w-full
px-3
py-1.5
text-base
font-normal
text-gray-700
bg-white bg-clip-padding
border border-solid border-gray-300
rounded
transition
ease-in-out
m-0
focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none "
type="text"
required
name="university"
autoComplete="true"
placeholder="Enter university"
value={input.university}
onChange={(e) => handleTeachingExpChange(index, e)}
/>
</div>
<div className="w-56 lg:w-40 p-2 xl:w-56">
<label className="text-sm font-light">Designation</label>
<input
className="form-control
block
w-full
px-3
py-1.5
text-base
font-normal
text-gray-700
bg-white bg-clip-padding
border border-solid border-gray-300
rounded
transition
ease-in-out
m-0
focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none "
type="text"
required
name="designation"
autoComplete="true"
placeholder="Enter designation"
value={input.designation}
onChange={(e) => handleTeachingExpChange(index, e)}
/>
</div>
<div className="w-56 lg:w-40 p-2 xl:w-56">
<label className="text-sm font-light">Period</label>
<input
className="form-control
block
w-full
px-3
py-1.5
text-base
font-normal
text-gray-700
bg-white bg-clip-padding
border border-solid border-gray-300
rounded
transition
ease-in-out
m-0
focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none "
type="text"
required
name="period"
autoComplete="true"
placeholder="Enter period"
value={input.period}
onChange={(e) => handleTeachingExpChange(index, e)}
/>
</div>
{teachingExp.length > 1 ? (
<TrashIcon
className="h-8 mt-5 mx-4 text-red-600"
onClick={() => removeTeachingExp(index)}
/>
) : (
""
)}
</div>
))}
<PlusCircleIcon
className="h-12 p-2 mx-4 text-[#020493] mt-1"
onClick={addTeachingExp}
/>
</div>
</div>
You are not properly updating state when adding new. Rewrite to this:
const addTeachingExp = () => {
let newTeachingExp = {
university: "",
designation: "",
period: "",
};
setTeachingExp([...teachingExp, newTeachingExp]); // HERE YOU FORGOT TO SPREAD IT INTO NEW ARRAY
};
Teaching experience is an array by updating state you missed to put it inside an array
Replace that one via
setTeachingExp(...teachingExp, newTeachingExp);
By this
setTeachingExp([...teachingExp, newTeachingExp]);
I've got a small formating problem. My CSS makes too long boxes (while I'm using the same CSS/Tailwind in the first column as the second one). If i remove flex, the problem disappears, but the content is no longer in the same row.
Here are some screenshots of the problem:
First (with flex) https://ctrlv.link/ova1 and https://ctrlv.link/zvp7
Secondary (without flex) https://ctrlv.link/MeHq
Code:
mostly just loading data and not that important stuff
import { useState, useEffect, useRef, useContext } from "react";
import { AppContext } from "/src/App";
import Axios from 'axios'
export default function Upgrader() {
const inputRefPerc = useRef(null)
const { userID } = useContext(AppContext);
const [ItemsList, setItemsList] = useState([])
const [Inventory, setInventory] = useState([])
useEffect(() => {
Axios.get(`http://localhost:3030/api/getItems`).then((response)=> {
setItemsList(response.data)
})
}, [])
useEffect(() => {
Axios.get(`http://localhost:3030/api/getInventory3/${userID}`).then((response)=> {
setInventory(response.data);
})
}, [])
return (
<div className="flex justify-center align-bottom">
<div className="bg-slate-800 rounded-cool text-white w-3/5 p-3">
<div className=" divide-y-2">
<h1 className="text-4xl font-bold text-slate-200 py-2" >
Upgrader 🔝
</h1>
<p/>
</div>
<div className="flex flex-row">
<div className="w-[40%] justify-center flex font-bold text-xl"><h1>Your Items</h1></div>
<div className="w-[20%] justify-center flex font-bold text-xl"><h1>Selector</h1></div>
<div className="w-[40%] justify-center flex font-bold text-xl"><h1>Possible Drops</h1></div>
</div>
This is where the problem happens -
<div className="flex flex-row">
First column
<div className="grid-cols-3 grid p-3 mt-2 w-[40%]">
{Inventory.map((val) => (
<div key={val.IDItem} className="cursor-pointer p-1.5 px-2 m-2 box-content rounded-cool bg-slate-700
hover:bg-gray-700 hover:m-0.5 hover:px-3 hover:border-2 hover:border-white-200">
<img className="" src={`src/images/skins/${val.SkinImage}`} alt={val.SkinImage}/>
<h1>{val.SkinName}</h1>
<h1>{val.QualityName}</h1>
<h1>{val.RarityName}</h1>
<h1>{val.ItemPrice} Tokens</h1>
</div>
))}
</div>
Secondary column
<div className="p-3 mt-2 w-[20%]">
<div className="cursor-pointer p-1.5 px-2 m-2 box-content rounded-cool bg-slate-700
hover:bg-gray-700 hover:border-2 hover:border-white-200 h-[15rem]
transition-all">
<h1>Placeholder</h1>
</div>
<div className="flex flex-auto justify-center">
<div className="cursor-pointer p-1.5 px-2 m-2 box-content rounded-cool bg-slate-700
hover:bg-gray-700 hover:border-2 hover:border-white-200
transition-all">
<h1 onClick={() => {inputRefPerc.current.value= 10}}>+10%</h1>
</div>
<div onClick={() => {inputRefPerc.current.value= 20}} className="cursor-pointer p-1.5 px-2 m-2 box-content rounded-cool bg-slate-700
hover:bg-gray-700 hover:border-2 hover:border-white-200
transition-all">
<h1>+20%</h1>
</div>
<div onClick={() => {inputRefPerc.current.value= 30}} className="cursor-pointer p-1.5 px-2 m-2 box-content rounded-cool bg-slate-700
hover:bg-gray-700 hover:border-2 hover:border-white-200
transition-all">
<h1>+30%</h1>
</div>
</div>
<div className="cursor-pointer p-1.5 px-2 m-2 box-content rounded-cool bg-slate-700
hover:bg-gray-700 hover:border-2 hover:border-white-200
transition-all flex flex-auto">
<h1 className="whitespace-nowrap">Chance: {""}</h1><input ref={inputRefPerc} type="number" min="1" max="100" className=" text-black w-[60px]"></input><h1>{""} %</h1>
</div>
<button
className=' border-2 border-green-700 bg-green-400 hover:bg-green-600 text-green-900 hover:text-rose-50 w-[100%] h-10 rounded-cool my-2 transition-all'
>
Let's go xd
</button>
</div>
The third column
<div className="grid-cols-3 grid p-3 mt-2 w-[40%]">
{ItemsList.map((val) => (
<div key={val.IDItem} className="cursor-pointer p-1.5 px-2 m-2 box-content rounded-cool bg-slate-700
hover:bg-gray-700 hover:m-0.5 hover:px-3 hover:border-2 hover:border-white-200
transition-all">
<img className="" src={`src/images/skins/${val.SkinImage}`} alt={val.SkinImage}/>
<h1>{val.SkinName}</h1>
<h1>{val.QualityName}</h1>
<h1>{val.RarityName}</h1>
<h1>{val.ItemPrice} Tokens</h1>
</div>
))}
</div>
</div>
</div>
</div>
);
}
I have successfully connected my custom server using Node.js and Express.js with Next.js. I'm trying to fetch a car by its id whenever I click it among other cars, so I can have that particular car only. But I keep getting an error saying params is undefined even though I get the id at the back of my link whenever I click on the single car in the browser. I've tried fetching the data using thunder client and everything works fine. I believe something is wrong with my frontend logic.
This is where I'm trying to fetch the data with the id
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
import Layout from "#/components/Layout";
import Image from "next/image";
import Link from "next/link";
import { useEffect, useState } from "react";
import Authorization from "#/HOC/Authorization";
import axios from "axios";
const Car = () => {
const [data, setData] = useState("");
const oneCar = async (params) => {
const { id } = params;
const res = await axios.get(`http://localhost:5000/one-car/${id}`);
setData(res.data);
if (res.status !== 200) {
console.log(res.status);
}
};
useEffect(() => {
oneCar();
}, []);
return (
<Layout>
{data && (
<div className="flex flex-col w-11/12 mx-auto mt-8 justify-center bg-blue-200 rounded-lg shadow">
<div className="flex w-full justify-center mt-6 px-4 mx-auto box-shadow-lg h-2/4 relative">
<Image
src="/assets/images/d17.jpg"
alt="shopping image"
className="mx-auto flex rounded-lg inset-0 w-full h-2/4 object-cover"
width={1000}
height={500}
/>
</div>
<form className="flex-auto p-6">
<div className="flex flex-wrap">
<h1 className="flex-auto text-xl font-semibold text-gray-800">
{data.carName}
</h1>
<div className="text-xl font-semibold text-gray-700 ">
{data.carPrice}
</div>
<div className="w-full flex-none text-sm font-medium text-gray-500 mt-2">
In stock
</div>
</div>
<div className="flex items-baseline mt-4 mb-6 text-gray-800 ">
<Link
href="#"
className="ml-auto hidden md:block text-sm text-gray-500 underline"
>
Size Guide
</Link>
</div>
<div className="flex mb-4 text-sm font-medium">
<button
type="button"
className="py-2 px-4 bg-blue-700 hover:bg-blue-800 focus:ring-indigo-500 focus:ring-offset-indigo-200 text-white w-full sm:w-1/4 transition ease-in duration-200 text-center text-base font-semibold shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 mx-auto rounded-lg "
>
Buy now
</button>
</div>
<p className="text-sm text-gray-500 text-center ">
Free shipping on all continental US orders.
</p>
</form>
</div>
)}
</Layout>
);
};
export default Authorization(Car);
This is where I fetch all cars and makes the id a parameter to the link address
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
import Image from "next/image";
import Layout from "#/components/Layout";
import Pagination from "#/components/Pagination";
import { GiBinoculars } from "react-icons/gi";
import { useGetAllCarsQuery } from "#/store/ReduxStore/getAllCarsApi";
import Link from "next/link";
const Market = () => {
//I use RTK Query to fetch the data, and It was successfully fetched
const { data, isLoading, error } = useGetAllCarsQuery();
return (
<Layout>
<div className="2xl:container 2xl:mx-auto">
<div className=" py-3 lg:px-20 md:px-6 px-4">
<div className=" flex justify-center mt-3 items-center">
<div className=" flex space-x-3 justify-center items-center">
<span className="bg-blue-800 px-4 py-2 rounded-md text-2xl text-white">
<GiBinoculars />
</span>
<input
type="search"
className="border-b-2 w-9/12 border-gray-700 -mb-3 leading-5 text-lg p-2 focus:outline-none"
placeholder="Search for cars here..."
/>
</div>
</div>
<hr className=" w-full bg-gray-200 my-6" />
<div className=" grid lg:grid-cols-4 sm:grid-cols-2 grid-cols-1 lg:gap-y-12 lg:gap-x-8 sm:gap-y-10 sm:gap-x-6 gap-y-6 lg:mt-12 mt-10">
{data?.map((cars, i) => (
<Link
key={i}
href="/[id]"
as={`${cars._id}`}
//I insert the id here
className="relative"
passHref
>
<div>
<div className=" relative group">
<div className="caroverlay"></div>
<Image
width={600}
height={400}
className="rounded-md w-full"
src="/assets/images/d17.jpg"
alt="A girl Posing Img"
/>
<div className=" absolute bottom-0 p-8 w-full opacity-0 group-hover:opacity-100 z-20">
<button className="text-base font-bold leading-4 text-gray-600 hover:bg-gray-300 hover:text-gray-700 bg-white py-3 w-full">
Add to your garage
</button>
<button className=" bg-transparent text-base font-bold leading-4 border-2 hover:bg-gray-300 hover:text-gray-700 border-white py-3 w-full mt-2 text-white">
View Car
</button>
</div>
</div>
<p className=" text-xl leading-5 text-gray-600 md:mt-6 mt-4">
{cars.carName}
</p>
<p className=" font-semibold text-xl leading-5 text-gray-800 mt-4">
<span>$</span> {cars.carPrice}
</p>
</div>
</Link>
))}
</div>
{/* _______________________________________________________ */}
<Pagination />
{/* _______________________________________________________ */}
</div>
</div>
</Layout>
);
};
export default Market;
Here is my backend logic
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
const router = require("express").Router();
const auth = require("../../middleware/auth");
const Car = require("../../Model/CarSchema");
router.get("/onecar/:id", auth, async (req, res) => {
try {
const car = await Car.findById(req.params.id);
res.status(200).json(car);
} catch (err) {
res.status(500).json({ msg: "Server Error" });
}
});
module.exports = router;
To access id in nextjs. I imported useRouter from next/router. Then I const router = useRouter(). Then const {id} = router.query
In my project whenever i run npm run build command it through an warning message thet
Warning: React Hook useEffect has a missing dependency: 'postImage'. Either include it or remove the dependency array. react-hooks/exhaustive-deps.
How to fix this. Thanks in advance. Here is my complete code in which i get this message.
import Image from 'next/image';
import {useRef} from 'react';
import { useSession } from "next-auth/client";
import {ChatAltIcon,ThumbUpIcon,ShareIcon} from "#heroicons/react/outline";
import{LoveIcon,SadEmojiIcon} from "#heroicons/react/solid";
import InsertEmotionIcon from "#material-ui/icons/InsertEmoticon"
import SentimentVeryDissatisfiedIcon from "#material-ui/icons/SentimentVeryDissatisfied";
import FavoriteIcon from "#material-ui/icons/Favorite";
import MoodIcon from "#material-ui/icons/Mood";
import MoodBadIcon from "#material-ui/icons/MoodBad";
import firebase from 'firebase';
import { db, storage } from "../firebases";
import {useEffect,useState} from 'react';
import {useCollection} from "react-firebase-hooks/firestore";
import "react-responsive-carousel/lib/styles/carousel.min.css"; // requires a loader
import { Carousel } from 'react-responsive-carousel';
const Post=({id,name,message,email,timestamp,postImage})=>{
const commentRef=useRef(null);
const [isShown, setIsShown] = useState(false);
const [session]=useSession();
const[totalImage,setTotalImage]=useState(null);
const[load,setLoaded]=useState(false);
const likePost= async(e)=>{
let min =1;
let max = 50;
let postId = e.target.getAttribute("id");
console.log(postId)
let userId = (Math.floor(Math.random()*(max-min+1))+min);
let reaction = e.target.getAttribute("data-reaction");
let item = {postId,userId,reaction};
console.log(reaction);
let send = await fetch("http://localhost:8000/api/backend",{
method:'post',
body:JSON.stringify(item),
headers:{
"Content-Type":'application/json',
"Accept":'application/json'
},
}).then(response=>{
console.log(response)
})
}
const[user,loading,error] = useCollection(
db.collection("users").orderBy("joined_at","desc")
);
const submitComment=async(e)=>{
if (!commentRef.current.value) return;
else
{
console.log("comment")
}
}
const handleEvent=(e)=>{
if(e.detail==2){
setIsShown(true)
}
else{
setIsShown(false)
}
}
useEffect(()=>{
const remainingImage=totalImage > 6 ? totalImage-6:0;
},[remainingImage])
return (
<div className="flex flex-col">
<div className="p-5 bg-white mt-5 router-t-2xl shadow-sm">
<div className="flex items-center space-x-2">
<div>
<p className="font-medium">{name}</p>
{
timestamp? <p className="text-xs text-gray-40">{timestamp}</p> :(
<p className="text-xs text-gray-40">Loading...</p>
)
}
</div>
</div>
<p className="pt-4">{message}</p>
</div>
<div className="relative h-56 bg-white">
{/* <div className="grid-cols-3 p-20 space-y-2 lg:space-y-0 lg:grid lg:gap-3 lg:grid-rows-3"> */}
<Carousel>
{
useEffect(()=>{
postImage?.map((ele)=>{
return ele.map((urls)=>{
setTotalImage(urls.url.length);
return urls.url.map((url_,index)=>{
return <div key={index} className="w-full rounded"><Image src={url_} layout="fill" objectFit="cover"alt="image"/></div>
})
})
})
},[session])
}
{/* </div> */}
</Carousel>
</div>
{
isShown &&(
<div className="flex justify-start items-center bg-white" >
<div className=" items-center px-1 p-2 rounded-xl corsor-pointer rounded-none rounded-bl-2xl">
<FavoriteIcon onClick={()=>setIsShown(false)}className="text-red hover:text-red-500"style={{color:"red"}}></FavoriteIcon>
</div>
<div className=" items-center p-2 px-1 rounded-xl corsor-pointer rounded-none rounded-bl-2xl">
<InsertEmotionIcon onClick={()=>setIsShown(false)}className="text-yellow hover:text-yellow-500" style={{color:"yellow"}}></InsertEmotionIcon>
</div>
<div className=" items-center p-2 px-1 rounded-xl corsor-pointer rounded-none rounded-bl-2xl">
<SentimentVeryDissatisfiedIcon onClick={()=>setIsShown(false)} className="text-yellow hover:text-yellow-500"style={{color:"yellow"}}></SentimentVeryDissatisfiedIcon>
</div>
<div className="items-center p-2 rounded-xl corsor-pointer rounded-none rounded-bl-2xl">
<MoodIcon onClick={()=>setIsShown(false)} className="text-yellow hover:text-yellow-500" style={{color:"yellow"}}></MoodIcon>
</div>
<div className=" items-center px-1 -1 p-2 rounded-xl corsor-pointer rounded-none rounded-bl-2xl">
<MoodBadIcon onClick={()=>setIsShown(false)} className="text-yellow hover:text-yellow-500"style={{color:"yellow"}}></MoodBadIcon>
</div>
</div>
)
}
<div className="flex justify-between items-center bg-white shadow-md text-gray-700 border-t mt-5">
<div onDoubleClick={handleEvent} className="flex items-center hover:bg-gray-100 flex-grow justify-content p-2 rounded-xl corsor-pointer rounded-none rounded-bl-2xl">
<ThumbUpIcon className="text-lg sm:text-base h-5 corsor-pointer"onClick={likePost} id={id} data-reaction="like" ></ThumbUpIcon>
<span className="cursor-pointer text-2xl text-gray-700">1223</span>
</div>
<div className="flex items-center hover:bg-gray-100 flex-grow justify-content p-2 rounded-xl corsor-pointer rounded-none">
<ChatAltIcon className="text-lg sm:text-base h-5 corsor-pointer"></ChatAltIcon>
<span className="cursor-pointer text-2xl text-gray-700">7777</span>
</div>
<div className="flex items-center hover:bg-gray-100 flex-grow justify-content p-2 rounded-xl corsor-pointer rounded-none rounded-bl-2xl">
<ShareIcon className="text-lg sm:text-base h-5 corsor-pointer"></ShareIcon>
<span className="cursor-pointer text-2xl text-gray-700">312</span>
</div>
</div>
<div className="flex space-x-4 p-4 py-1 items-center bg-white ">
{session ? <><Image src={session.user.image} height={40} width={40} layout="fixed"className="rounded-full"alt="image"/> </>:null
}
<form className="flex flex-1">
<input className="rounded-full h-12 bg-gray-100 flex-grow px-5 focus:outline-none" ref={commentRef} type="text"placeholder="Comment..."/>
<button hidden type="submit"onClick={submitComment}></button>
</form>
</div>
<div className="rounded-b-2xl bg-white flex text-gray-40 pb-2 pl-4 ">
<small className="mx-auto">Press enter to submit your comment.</small>
</div>
</div>
)
}
export default Post;
You can :
Use // eslint-disable-next-line react-hooks/exhaustive-deps on top of the line causing the error
Disable this eslint rule in .eslintrc.json
Simply include the missing variable in the useEffect dependency array ([session, postImage])
I built a sign up page for my web app using react, here is the code:
import React, { useCallback, useState } from "react";
import { withRouter } from "react-router";
import app from "../base";
const SignUp = ({ history }) => {
const handleSignUp = useCallback(
async (event) => {
event.preventDefault();
const { email, password } = event.target.elements;
try {
await app
.auth()
.createUserWithEmailAndPassword(email.value, password.value);
history.push("/");
} catch (error) {
alert(error);
}
},
[history]
);
const [firstName, setFirstname] = useState('');
const handleFirstNameInput = e => {
setFirstname(e.target.current.value);
};
const logName = () => {
alert(firstName);
};
return (
<div className="flex h-screen">
<form
className="w-full max-w-lg m-auto border-solid border-4 border-gray-600 p-6 rounded-lg"
onSubmit={handleSignUp}
>
<div className="flex flex-wrap -mx-3">
{/* Div for first name field */}
<div className="w-full md:w-1/2 px-3 mb-6 md:mb-0">
<label
className="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
htmlFor="grid-first-name"
>
First Name
</label>
<input
className="appearance-none block w-full bg-gray-200 text-gray-700 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white"
id="grid-first-name"
type="text"
placeholder="Ramon"
onChange={handleFirstNameInput}
value={firstName}
/>
</div>
{/* Div for last name */}
<div className="w-full md:w-1/2 px-3">
<label
className="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
htmlFor="grid-last-name"
>
Last Name
</label>
<input
className="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
id="grid-last-name"
type="text"
placeholder="Wenzel"
/>
</div>
</div>
<div className="flex flex-wrap -mx-3 mb-6">
{/* Div for email */}
<div className="w-full px-3">
<label
className="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
htmlFor="grid-password"
>
Email
</label>
<input
className="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
id="grid-email"
type="email"
placeholder="123#example.com"
/>
</div>
{/* Div for password */}
<div className="w-full px-3">
<label
className="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
htmlFor="grid-password"
>
Password
</label>
<input
className="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
id="grid-password"
type="password"
placeholder="******************"
/>
</div>
</div>
<div className="md:flex md:items-center">
{/* Submit Button */}
<button
className="shadow bg-purple-500 hover:bg-purple-400 focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded"
type="submit"
onClick={logName}
>
Sign Up
</button>
</div>
</form>
</div>
);
};
export default withRouter(SignUp);
however I keep getting TypeError: Cannot read property 'value' of undefined.
Does anyone have any ideas pls help me with this!
Also, I'm trying to get the first name of user here and put it into my home.js(homepage), how to export the first name here and put it into another js file?
Change this
setFirstname(e.target.current.value)
to
setFirstname(e.target.value)
There is no current property on event.target.
You might have confused with event.currentTarget. But that's a bit different.
You could check the difference between event.currentTarget and event.target here -> https://joequery.me/code/event-target-vs-event-currenttarget-30-seconds/