map.panTo does not animate when moving back to the center - javascript

I have a reactjs app that shows the google map. In the map section, there is a center marker. I also have button that when clicked, the map should smoothly move back to the center. Now, the button does work, but it does not animate. Kindly help.
The center is from derived coordinates. Also, if anyone knows how I can define the coordinates using the geolocator to get the current location on the map, kindly help.
This is my code
import React, { useState, useEffect, useRef } from 'react';
import { Link, useNavigate } from "react-router-dom";
import Menubar from "../../components/menubar/Menubar"
import axios from 'axios';
import { UserContext } from "../../UserContext";
import toast, { Toaster } from 'react-hot-toast';
import ActionSheet from "actionsheet-react";
import { useJsApiLoader, GoogleMap, Marker, Autocomplete, DirectionsRenderer } from '#react-google-maps/api'
import Skeleton from 'react-loading-skeleton';
function AddFarm() {
let navigate = useNavigate();
const [loading, setLoading] = useState(false);
const user = React.useContext(UserContext);
const [show, setShow] = useState(false);
const ref = useRef();
const handleOpen = () => {
ref.current.open();
};
const handleClose = () => {
ref.current.close();
}
const center = { lat: -1.1797562, lng: 36.9064927 }
const { isLoaded } = useJsApiLoader({
googleMapsApiKey: process.env.REACT_APP_GOOGLE_MAPS_API_KEY,
libraries: ['places'],
})
const [map, setMap] = useState(/** #type google.maps.Map */(null))
if (!isLoaded) {
return <Skeleton />
}
return (
<div>
<Menubar />
<div className="appHeader bg-primary text-light">
<div className="left">
<a onClick={() => navigate(-1)} className="headerButton goBack">
<i className="fi fi-rr-angle-left"></i> </a>
</div>
<div className="pageTitle">Add Farm</div>
<div className="right">
</div>
</div>
<div id="appCapsule">
<div className="section mt-3 mb-3">
<form onSubmit={submitFarm}>
<div className="form-group basic">
<div className="input-wrapper">
<label className="label" >Name</label>
<input type="text" className="form-control" onChange={handleInput} value={farmInput.farmname} name="farmname" placeholder=" Enter farm name" />
<i className="clear-input">
<i className="fi fi-rr-cross-circle"></i> </i>
</div>
<div className="invalid-feedback">
{errorlist.farmname}
</div>
<div className="input-info">Give your farm a name</div>
</div>
<div className="form-group basic">
<div className="input-wrapper">
<label className="label" >County</label>
<select className="form-control custom-select" onChange={handleInput} value={farmInput.county_id} name="county_id">
<option value="0">Select County</option>
{
county && county.map((item) => {
return (
<option value={item.id} key={item.id}>{item.countyname}</option>
)
})
}
</select>
</div>
<div className="invalid-feedback">
{errorlist.county_id}
</div>
<div className="input-info">Enter the county your farm is</div>
</div>
<div className="form-group basic">
<div className="input-wrapper">
<label className="label" >Location</label>
<input type="text" className="form-control" onChange={handleInput} value={farmInput.farmlocation} name="farmlocation"
placeholder="Enter farm location" />
<i className="clear-input">
<i className="fi fi-rr-cross-circle"></i> </i>
</div>
<div className="input-info">Enter exactly where you farm is located</div>
</div>
<div className="mt-2">
<button onClick={handleOpen} className="btn btn-primary btn-block btn-lg">Map your Farm</button>
</div>
<ActionSheet
ref={ref}
mouseEnable={false}
touchEnable={false}
sheetStyle={{
borderTopLeftRadius: 0,
borderTopRightRadius: 0,
height: '100%'
}}>
<div className="appHeader bg-primary text-light">
<div className="left">
<a onClick={() => setShow(true)} className="headerButton toggle-searchbox">
<i className="fi fi-rr-search"></i> </a>
</div>
<div className="pageTitle">Map your Farm</div>
<div className="right">
<a onClick={handleClose} className="headerButton">
<i className="fi fi-rr-cross"></i></a>
</div>
</div>
<div id="search" className={show ? "appHeader no-boxshadow show" : "appHeader"}>
<div className="search-form">
<div className="form-group searchbox">
<input type="text" className="form-control" placeholder="Search..." />
<i className="input-icon">
<i className="fi fi-rr-search"></i> </i>
<a onClick={() => setShow(false)} className="ml-1 close toggle-searchbox">
<i className="fi fi-rr-cross-circle"></i> </a>
</div>
</div>
</div>
<div className="section full mt-6 h100">
<GoogleMap
center={center}
zoom={18}
mapContainerStyle={{ width: '100%', height: '100%' }}
options={{
zoomControl: false,
streetViewControl: false,
mapTypeControl: false,
fullscreenControl: false,
mapTypeId: "satellite"
}}
onLoad={map => setMap(map)}
>
<Marker position={center} />
</GoogleMap>
<div class="fab-button animate bottom-right dropdown show bottom-high">
<a onClick={() => {
map.panTo(center, { animate: true, duration: 2.0 })
map.setZoom(18)
}} class="fab" data-toggle="dropdown" aria-expanded="true">
<i class="fi fi-rr-marker"></i>
</a>
</div>
<div className="form-button-group transparent-bg">
<button className="btn btn-primary btn-block btn-lg spinner-btn">{loading ? <><span className="spinner-border spinner-border-sm mr-05" role="status" aria-hidden="true"></span>Updating Profile</> : <>Update Profile</>}</button>
</div>
</div>
</ActionSheet>
</form>
</div>
</div>
</div>
);
}
export default AddFarm;

Related

How do I add some HTML panels from my Modal to my web page the 'React way'

I have 2 Components, ApplicationOverview.js and ApplicationModal.jsx. Basically, I have a button "Add Application" on my ApplicationOverview.js page which opens the Modal in which I want to fill in some input fields and upload an image there, which is then shown on the ApplicationOverview page as a panel through predefined HTML.
The way I currently implemented it is with the .insertAdjacentHTML method which works, but on the one hand I've been told that implementing it this way makes my page vulnerable to XSS, and on the other hand, events that are added like this are not working. Is there a safe way to let React handle this by passing the HTML to ApplicationOverview.js and append it to an existing div element? Nothing I have searched for so far has worked for me.
ApplicationModal.jsx:
import React from "react";
import placeholder from "../icons/placeholder.png";
var name = "";
var comment = "";
var filename = "";
var id = 0;
const ApplicationModal = ({ setOpen }) => {
const [state, setState] = React.useState("");
const [stateComment, setStateComment] = React.useState(placeholder);
const [file, setFile] = React.useState({placeholder});
React.useEffect(() => {
function handleEscapeKey(event) {
if (event.code === "Escape") {
setOpen(false);
}
}
document.addEventListener("keydown", handleEscapeKey);
return () => document.removeEventListener("keydown", handleEscapeKey);
});
const handleComment = (e) => {
setStateComment(e.target.value);
};
const handleChange = (e) => {
setState(e.target.value);
};
//Method which adds new panels to ApplicationOverview.js
const addNewApplication = () => {
if (state !== "" && stateComment !== "") {
document
.getElementById("center")
.insertAdjacentHTML(
"beforeend",
`<div class='overview-box' id=${id}> <img class='image' src=${file} alt='placeholder'/> <div class='box-content'><h3 class='overview-h3' id='new-headline'>${state}</h3> <p class='overview-p'>${stateComment}</p><h3 class='overview-h3-second'>Connected Products</h3><h1 class='overview-h1-second'> ?/? <p class='overview-p-second'>Online</p> </h1> <div class='module-button' id='configure'> <button type='button' class='btn btn-secondary'></button> <div class='button-animation'></div> <div class='button-content'> <span class='content-text'>Configure</span> </div> </div> </div> </div>`
);
id++;
setOpen(false);
} else if (state === "" && stateComment !== "") {
document
.getElementById("center")
.insertAdjacentHTML(
"beforeend",
`<div class='overview-box' id = ${id}> <img class='image' src=${file} alt='placeholder'/> <div class='box-content'><h3 class='overview-h3' id='new-headline'>${state}</h3> <p class='overview-p'>${stateComment}</p><h3 class='overview-h3-second'>Connected Products</h3><h1 class='overview-h1-second'> ?/? <p class='overview-p-second'>Online</p> </h1> <div class='module-button' id='configure'> <button type='button' class='btn btn-secondary'></button> <div class='button-animation'></div> <div class='button-content'> <span class='content-text'>Configure</span> </div> </div> </div> </div>`
);
id++;
setOpen(false);
} else if (state !== "" && stateComment === "") {
document
.getElementById("center")
.insertAdjacentHTML(
"beforeend",
`<div class='overview-box' id=${id}> <img class='image' src=${file} alt='placeholder'/> <div class='box-content'><h3 class='overview-h3' id='new-headline'>${state}</h3> <p class='overview-p'>${stateComment}</p><h3 class='overview-h3-second'>Connected Products</h3><h1 class='overview-h1-second'> ?/? <p class='overview-p-second'>Online</p> </h1> <div class='module-button' id='configure'> <button type='button' class='btn btn-secondary'></button> <div class='button-animation'></div> <div class='button-content'> <span class='content-text'>Configure</span> </div> </div> </div> </div>`
);
id++;
setOpen(false);
} else {
alert("Please fill in atleast one value.");
}
};
function openDialog() {
document.getElementById("inputUpload").click();
}
function loadFile(e) {
console.log(e.target.files);
setFile(URL.createObjectURL(e.target.files[0]));
}
document.addEventListener("click", function(e) {
})
name = state;
comment = stateComment;
filename = file;
return (
<React.Fragment>
<div className="modalDark" style={{ paddingRight: "250px" }}>
<div class="modal-dialog">
<div class="modal-content" style={{ width: "800px" }}>
<div class="modal-close">
<div class="module-button" style={{ left: "750px" }}>
<button
class="btn btn-link "
onClick={() => setOpen(false)}
></button>
<div class="button-animation"></div>
<div class="button-content new">
<i class="icon icon-dc_close"></i>
</div>
</div>
</div>
<div class="modal-header">
<h3>Add new Application</h3>
</div>
<div class="modal-body">
<div
class="module-input form-group has-placeholder"
data-plugin="moduleInput"
style={{ bottom: "60px", width: "350px" }}
>
<label for="demo-default">Customer Name</label>
<div class="input-animation-wrapper">
<input
type="text"
id="demo-default"
class="form-control "
value={state}
maxLength="42"
placeholder="[Application Name]"
onChange={(e) => handleChange(e)}
/>
<div class="input-animation"></div>
</div>
</div>
<div
class="module-textarea form-group floating-label has-placeholder"
data-plugin="moduleInput"
style={{ bottom: "60px" }}
>
<label for="demo-3">Customer Short text</label>
<div
class="input-animation-wrapper"
style={{ width: "350px" }}
>
<textarea
id="demo-3"
class="form-control"
rows="9"
placeholder="Short description of Customer; max. 280 characters"
maxLength={180}
value={stateComment}
onChange={(e) => handleComment(e)}
style={{ width: "350px" }}
></textarea>
<div class="label-area"></div>
<div class="input-animation"></div>
</div>
</div>
<img
class="image"
alt="Customer Logo"
id="logo"
src={file}
style={{
left: "420px",
bottom: "280px",
position: "absolute",
height: "250px",
}}
/>
<div
class="module-button"
style={{
left: "500px",
bottom: "200px",
position: "absolute",
zIndex: "1",
}}
>
<button
type="file"
class="btn btn-light"
onClick={() => openDialog()}
id="fileUpload"
>
<input
type="file"
hidden={true}
accept="image/*"
id="inputUpload"
onChange={(e) => loadFile(e)}
></input>
</button>
<div class="button-animation"> </div>
<div class="button-content">
<span class="content-text">Upload Logo</span>
</div>
</div>
<div
class="module-button"
style={{ bottom: "50px", width: "100px", textAlign: "center" }}
>
<button
type="button"
class="btn btn-secondary btn"
onClick={() => addNewApplication()}
id="adding"
></button>
<div class="button-animation"></div>
<div class="button-content">
<span class="content-text">Add</span>
</div>
</div>
</div>
</div>
</div>
</div>
</React.Fragment>
);
};
export default ApplicationModal;
export { name, comment, filename };
ApplicationOverview.js:
import React from "react";
import placeholder from "../icons/placeholder.png";
import ApplicationModal from "../components/ApplicationModal.jsx";
const ApplicationOverview = () => {
const [open, setOpen] = React.useState(false);
return (
<div id="wrapper">
{open && <ApplicationModal setOpen={setOpen} />}
<div class="component-headline">
<h4 style={{ color: "gray", display: "inline" }}>
Application overview
</h4>
<div
class="module-button"
style={{
backgroundColor: "rgb(18,205,212,255)",
borderRadius: "12px",
marginLeft: "1032px",
}}
onClick={() => setOpen(true)}
>
<button type="button" class="btn btn-secondary"></button>
<div class="button-animation"></div>
<div
class="button-content"
style={{
backgroundColor: "rgb(18,205,212,255)",
borderRadius: "12px",
}}
>
<span class="content-text" style={{ color: "black" }}>
Add Application
</span>
</div>
</div>
</div>
<hr style={{ marginTop: "-20px" }} />
<!-- This is where the added content should be appended to, below are three examples -->
<!-- of hardcoded panels that should be normally added through the Modal" -->
<div class="center-content" id="center">
<div class="overview-box">
<img
class="image"
src={placeholder}
alt="placeholder"
/>
<div class="box-content">
<h3 class="overview-h3">Press</h3>
<p class="overview-p">This Application is used for maintenance</p>
<h3 class="overview-h3-second">Connected Products</h3>
<h1 class="overview-h1-second">
?/?
<p class="overview-p-second">Online</p>
</h1>
<div class="module-button" id="configure">
<button type="button" class="btn btn-secondary"></button>
<div class="button-animation"></div>
<div class="button-content">
<span class="content-text">Configure</span>
</div>
</div>
</div>
</div>
<div class="overview-box">
<img
class="image"
src={placeholder}
alt="placeholder"
/>
<div class="box-content">
<h3 class="overview-h3">Tooling Machine</h3>
<p class="overview-p">
This Application is used for drilling records
</p>
<h3 class="overview-h3-second">Connected Products</h3>
<h1 class="overview-h1-second">
?/?
<p class="overview-p-second">Online</p>
</h1>
<div class="module-button" id="configure">
<button type="button" class="btn btn-secondary"></button>
<div class="button-animation"></div>
<div class="button-content">
<span class="content-text">Configure</span>
</div>
</div>
</div>
</div>
<div class="overview-box">
<img
class="image"
src={placeholder}
alt="placeholder"
/>
<div class="box-content">
<h3 class="overview-h3">Storing Unit</h3>
<p class="overview-p">
This Application is used to store parameters
</p>
<h3 class="overview-h3-second">Connected Products</h3>
<h1 class="overview-h1-second">
?/?
<p class="overview-p-second">Online</p>
</h1>
<div class="module-button" id="configure">
<button type="button" class="btn btn-secondary"></button>
<div class="button-animation"></div>
<div class="button-content">
<span class="content-text">Configure</span>
</div>
</div>
</div>
</div>
</div>
</div>
);
};
export default ApplicationOverview;
Modal Window
ApplicationOverview
You can put your useState in the ApplicationOverview.js and pass them as props to the ApplicationModal. So when the applicationModal set the useState the ApplicationOverview has the data and can simply display it.
in your ApplicationOverview:
const [state, setState] = React.useState("");
const [stateComment, setStateComment] = React.useState(placeholder);
const [file, setFile] = React.useState({placeholder});
return (
<div id="wrapper">
{open && <ApplicationModal setOpen={setOpen} setState={setState} state={state} setFile={setFile} file={file} setStateComment={setStateComment} stateComment={stateComment}/>
rest of your HTML
)
then where you want to display the result in the ApplicationOverview you can:
{state && stateComment { display what you want}}

userData is not defined under useState React JS

My code is malfunctioning and showing TypeError: userData is undefined error. I am taking data from MongoDB to show on the website.
{userData.name} is creating the trouble. set user data part of UseState is working fine and am getting the data in the console from MongoDB. The error seems to be in the frontend part.
Code:-
import PropTypes from "prop-types";
import React, { Fragment, useEffect, useState } from "react";
import MetaTags from "react-meta-tags";
import { BreadcrumbsItem } from "react-breadcrumbs-dynamic";
import Card from "react-bootstrap/Card";
import Accordion from "react-bootstrap/Accordion";
import LayoutOne from "../../layouts/LayoutOne";
import Breadcrumb from "../../wrappers/breadcrumb/Breadcrumb";
import { useHistory } from "react-router-dom";
const MyAccount = ({ location }) => {
const { pathname } = location;
const history = useHistory();
const [userData, setUserData] = useState();
const callAccount = async () => {
try {
const res = await fetch('/myaccount', {
method: 'GET',
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
credentials: "include"
});
const data = await res.json();
console.log(data);
setUserData(data);
if (!res.status === 200)
{
const error = new Error(res.error);
throw error;
}
} catch (err) {
console.log(err);
history.push('/login')
}
}
useEffect(() => {
callAccount();
}, []);
return (
<Fragment>
<MetaTags>
<title>Flone | My Account</title>
<meta
name="description"
content="Compare page of flone react minimalist eCommerce template."
/>
</MetaTags>
<BreadcrumbsItem to={process.env.PUBLIC_URL + "/"}>Home</BreadcrumbsItem>
<BreadcrumbsItem to={process.env.PUBLIC_URL + pathname}>
My Account
</BreadcrumbsItem>
<LayoutOne headerTop="visible">
{/* breadcrumb */}
<Breadcrumb />
<div className="myaccount-area pb-80 pt-100">
<div className="container">
<div className="row">
<div className="ml-auto mr-auto col-lg-9">
<div className="myaccount-wrapper">
<form method="GET">
<Accordion defaultActiveKey="0">
<Card className="single-my-account mb-20">
<Card.Header className="panel-heading">
<Accordion.Toggle variant="link" eventKey="0">
<h3 className="panel-title">
<span>1 .</span> My account information{" "}
</h3>
</Accordion.Toggle>
</Card.Header>
<Accordion.Collapse eventKey="0">
<Card.Body>
<div className="myaccount-info-wrapper">
<div className="account-info-wrapper">
<h5>Your Personal Details { userData.name}</h5>
</div>
<div className="row">
<div className="col-lg-6 col-md-6">
<div className="billing-info">
<label>First Name </label>
<input type="text" />
</div>
</div>
<div className="col-lg-6 col-md-6">
<div className="billing-info">
<label>Last Name</label>
<input type="text" />
</div>
</div>
<div className="col-lg-12 col-md-12">
<div className="billing-info">
<label>Email Address</label>
<input type="email" />
</div>
</div>
<div className="col-lg-6 col-md-6">
<div className="billing-info">
<label>Telephone</label>
<input type="text" />
</div>
</div>
<div className="col-lg-6 col-md-6">
<div className="billing-info">
<label>Fax</label>
<input type="text" />
</div>
</div>
</div>
</div>
</Card.Body>
</Accordion.Collapse>
</Card>
<Card className="single-my-account mb-20">
<Card.Header className="panel-heading">
<Accordion.Toggle variant="link" eventKey="1">
<h3 className="panel-title">
<span>2 .</span> Change your password
</h3>
</Accordion.Toggle>
</Card.Header>
<Accordion.Collapse eventKey="1">
<Card.Body>
<div className="myaccount-info-wrapper">
<div className="account-info-wrapper">
<h4>Change Password</h4>
<h5>Your Password</h5>
</div>
<div className="row">
<div className="col-lg-12 col-md-12">
<div className="billing-info">
<label>Password</label>
<input type="password" />
</div>
</div>
<div className="col-lg-12 col-md-12">
<div className="billing-info">
<label>Password Confirm</label>
<input type="password" />
</div>
</div>
</div>
</div>
</Card.Body>
</Accordion.Collapse>
</Card>
<Card className="single-my-account mb-20">
<Card.Header className="panel-heading">
<Accordion.Toggle variant="link" eventKey="2">
<h3 className="panel-title">
<span>3 .</span> Modify your address book entries{" "}
</h3>
</Accordion.Toggle>
</Card.Header>
<Accordion.Collapse eventKey="2">
<Card.Body>
<div className="myaccount-info-wrapper">
<div className="account-info-wrapper">
<h4>Address Book Entries</h4>
</div>
<div className="entries-wrapper">
<div className="row">
<div className="col-lg-12 col-md-12 d-flex align-items-center justify-content-center">
<div className="entries-info text-center">
<p>John Doe</p>
<p>Paul Park </p>
<p>Lorem ipsum dolor set amet</p>
<p>NYC</p>
<p>New York</p>
</div>
</div>
</div>
</div>
<div className="billing-back-btn">
<div className="billing-btn">
<button type="submit">Continue</button>
</div>
</div>
</div>
</Card.Body>
</Accordion.Collapse>
</Card>
</Accordion>
</form>
</div>
</div>
</div>
</div>
</div>
</LayoutOne>
</Fragment>
);
};
MyAccount.propTypes = {
location: PropTypes.object
};
export default MyAccount;
Because the initial of userData is undefined. Just update it with an object
const [userData, setUserData] = useState({});
const [userData, serUserData] = useState();
The initial value is the argument you pass to useState.
You haven't passed any value, so it is initially undefined.
At some point in the future the Ajax request will come back and you might call setUserData to assign a different value, but by then you've tried to read userData.name and thrown an exception.
You need to account for that in your code. A typical approach would be to do something like:
if (!userData) {
return <ALoadingComponent />
}
return /* what you have now */

am Unable to calculate the prices in the cart List-ReactJS

I am doing a cart page here, the cart page will display the items to the which user has been added and it will display its price also. On the same page, i want to display the Grand total amount of all the items present on the cart Page in Payment Summary(order summary)
Please help me am new to React.
Here is my ReactJS code of Cart page
import React, { useEffect, useState } from 'react';
import { useHistory } from 'react-router';
import '../cart.css';
function Cart() {
const tvalue = 0;
const [cart, setCart] = useState([]);
const [paymentsummery, setpaymentsummery] = useState(0);
const [total, setTotal] = useState('');
const [loading, setLoading] = useState(true);
const [cartSate, setcartState] = useState(true);
const [id, setID] = useState('');
const history = useHistory();
useEffect(() => {
const fetchUser = async () => {
try {
const responce = await fetch('/getcartItems', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
const resp = await responce.json();
console.log(resp);
setCart(resp);
setLoading(false);
setID(resp[0]._id);
setcartState(true);
if (!responce) {
alert('user not authorized');
history.push('/');
} else if (responce.status == 400) {
history.push('/');
} else if (responce.status == 401) {
alert('cart is empty');
}
} catch {
// alert('cart is empty')
setcartState(false);
}
};
fetchUser();
}, []);
if (cartSate == true) {
return (
<div className="cart_cont row container-fluid">
{loading ? (
<div className="loading_div">
<h1 className="loading">Loading...</h1>
</div>
) : (
cart.map((itms, index) => (
<div key={index} className="innerCart my-0 col-8">
<div className="cartDetails">
<div className="slno d-flex flex-column">
<label htmlFor="" className="text-danger m-auto">
Sl.No
</label>
<p className="m-auto">{index + 1}</p>
</div>
<div className="cartImage ">
<img
src={itms.productimage}
alt="cart_image"
height="100px"
/>
</div>
<div className="title d-flex flex-column">
<label htmlFor="" className="text-danger m-auto">
Item Name
</label>
<p className="m-auto">{itms.productname}</p>
</div>
<div className="qty d-flex flex-column">
<label htmlFor="" className="text-danger m-auto">
Quantity
</label>
<p className="m-auto">{itms.qty}</p>
</div>
<div className="tprice d-flex flex-column">
<label htmlFor="" className="text-danger m-auto">
Price
</label>
<p className="m-auto">{itms.totalprice}</p>
</div>
<div className="d-flex ">
<i className="fas fa-trash m-auto" />
</div>
</div>
<hr />
</div>
))
)}
{loading ? (
<div />
) : (
<div className="priceDetails col-4 ">
<div className="innerPriceDetails rounded">
<h1 className="paymentSummery h3 p-2">Payment Summery </h1>
<div className=" d-flex justify-content-between mx-2 my-2">
<span>Transaction code</span>
<span>Vd7jl0rq9ppe</span>
</div>
<div className="coupen d-flex m-3 justify-content-between">
<input
type="text"
className="form-control mr-2"
placeholder="COUPON CODE"
/>
<button className="btn btn-info px-5">Apply</button>
</div>
<hr />
<div className="order_summery m-3">
<div className="d-flex justify-content-between">
<h5>Order Summery</h5>
<h5>Rs. </h5>
</div>
<div className="d-flex justify-content-between">
<h5>Shipping charges</h5>
<h5>Rs. 10</h5>
</div>
<div className="d-flex justify-content-between">
<h5>Additional services</h5>
<h5>Rs. 00</h5>
</div>
<div className="d-flex justify-content-between">
<h5 className="font-weight-bold">Total amount</h5>
<h5 className="font-weight-bold">Rs. 5400</h5>
</div>
<hr />
<p className="d-flex bg-danger expires text-white p-2 rounded justify-content-between">
Sale Expires in: 21Hours, 31 Minutes
</p>
</div>
</div>
<button className="btn btn-warning w-100 my-3 font-weight-bold p-2">
CHECKOUT
</button>
</div>
)}
</div>
);
}
return (
<div>
<h1 className="display-3 mt-5">CART IS EMPTY!</h1>
</div>
);
}
export default Cart;
above, I have shared my whole code of the cart page, Usually, the cart data will be displayed from the database.
Please help me.
For that, you would use Array.reduce to calculate for grandTotal:
Before your return function:
const grandTotal = cart.reduce((a, c) => a + c.totalprice, 0);
Then you can place grandTotal where ever you want to display it.

Filter not working proper in react its working only for first time also how to filter true and false

Here is my code
https://stackblitz.com/edit/react-nsxxqp?file=src%2FApp.js
and my local code is here how to filter i don't know i am new for react and JavaScript please help me i don't know how to finish my task.
import React, { useEffect, useState } from "react";
const Product = (props) => {
const [allButtons, setAllButtons] = useState([]);
const [product, setProduct] = useState([]);
useEffect(() => {
fetch("https://api.spacexdata.com/v3/launches?limit=100")
.then(response => response.json())
.then(productsList => {
setProduct(productsList);
setAllButtons(productsList);
});
}, []);
const onBtnClick = (e) =>{
setProduct(product.filter(i=>i.launch_year == e));
};
return(
<div className="container-fluid">
<div className="row">
<div className="col-xl-12">
<h2>SpacesX Launch Programme</h2>
</div>
</div>
<div className="row">
<div className="col-xl-2 col-lg-2 col-md-2 col-sm-2 col-xs-12">
<div className="inner">
<p className="bold">Filter</p>
<div className="col12 launchYear">
<p className="marg0">Launch Year</p>
{allButtons.map(productYr => (
<button
className="btn btn-primary btnSpacex"
key={productYr.launch_year}
onClick={(e) => onBtnClick(productYr.launch_year)}
>
{productYr.launch_year}
</button>
))}
</div>
<div className="clearfix" />
<div className="col12 launchYear">
<p className="marg0">Successful Launch</p>
<button className="btn btn-default btnSpacex">True</button>
<button className="btn btn-default btnSpacex">False</button>
</div>
<div className="clearfix" />
<div className="col12 launchYear">
<p className="marg0">Successful Landing</p>
<button className="btn btn-default btnSpacex">True</button>
<button className="btn btn-default btnSpacex">False</button>
</div>
</div>
</div>
<div className="col-xl-10 col-lg-10 col-md-10 col-sm-10 col-xs-12 items1">
<div className="row">
{product.map(product => (
<div
key={product.flight_number}
className="col-xl-3 col-lg-3 col-md-3 col-sm-3 col-xs-12 marginBottom15"
>
<div className="inner">
<img
src={product.links.mission_patch}
className="full-width imgBg"
alt={product.mission_name}
/>
<div className="clearfix" />
<p className="productName bold margBot5">
{product.mission_name} #{product.flight_number}
</p>
<div className="clearfix" />
<p className="bold margBot5">
Mission Ids:
<ul className="marg0 blueClr">
<li>{product.mission_id}</li>
</ul>
</p>
<div className="clearfix" />
<p className="bold margBot5">
Launch Year:{" "}
<span className="normal blueClr">
{product.launch_year}
</span>
</p>
<div className="clearfix" />
<p className="bold margBot5">
Successful Launch:{" "}
<span className="normal blueClr">
{product.launch_success}
</span>
</p>
<div className="clearfix" />
<p className="bold margBot5">
Successful Landing:{" "}
<span className="normal blueClr">
{product.rocket.land_success}
</span>
</p>
</div>
</div>
))}
</div>
</div>
</div>
</div>
)
}
export default Product
Main issue here is your onButtonClick function. Change it to the following code (instead of product.filter, use allButtons.filter):
const onBtnClick = e => {
setProduct(allButtons.filter(i => i.launch_year == e));
};
The problem was that you had all of your products, then when you selected the first button, you set the product to just that button. On the next click, you're trying to filter on just the single product that you selected in the first click. To get around this, you want the filter to always be on the allButtons list (I'm assuming this was just a small oversight on your part, it looks like you knew exactly what you were trying to do but just accidentally put the wrong list in the function).
Another small change that I would make to your code is below: (introduce index parameter and use it as the key):
{allButtons.map((productYr, index) => (
<button
className="btn btn-primary btnSpacex"
key={index}
onClick={e => onBtnClick(productYr.launch_year)}
>
{productYr.launch_year}
</button>
))
}
This will eliminate all those console warnings that you're getting for having duplicate keys.
Check below code
import React, { useEffect, useState } from "react";
const Product = (props) => {
const [allButtons, setAllButtons] = useState([]);
const [launchSuccess, launchAllSuccess] = useState([]);
const [landSuccess, landAllSuccess] = useState([]);
const [product, setProduct] = useState([]);
useEffect(() => {
fetch("https://api.spacexdata.com/v3/launches?limit=100")
.then(response => response.json())
.then(productsList => {
setProduct(productsList);
setAllButtons(productsList);
launchAllSuccess(productsList);
landAllSuccess(productsList);
});
}, []);
const onBtnClick = e => {
setProduct(allButtons.filter(i => i.launch_year === e));
};
const onBtnLaunchAllSuccess = e =>{
setProduct(launchSuccess.filter(i => i.launch_success === e));
}
const onBtnLandSuccessful = e =>{
setProduct(landSuccess.filter(i => i.rocket.first_stage.cores[0].land_success === e));
}
return(
<div className="container-fluid">
<div className="row">
<div className="col-xl-12">
<h2>SpacesX Launch Programme</h2>
</div>
</div>
<div className="row">
<div className="col-xl-2 col-lg-2 col-md-2 col-sm-2 col-xs-12">
<div className="inner">
<p className="bold">Filter</p>
<div className="col12 launchYear">
<p className="marg0">Launch Year</p>
{allButtons.map((productYr, index) => (
<button
className="btn btn-primary btnSpacex"
key={index}
onClick={e => onBtnClick(productYr.launch_year)}
>
{productYr.launch_year}
</button>
))
}
</div>
<div className="clearfix" />
<div className="col12 launchYear">
<p className="marg0">Successful Launch</p>
<button
onClick={e => onBtnLaunchAllSuccess(true)}
className="btn btn-default btnSpacex">True</button>
<button
onClick={e => onBtnLaunchAllSuccess(false)}
className="btn btn-default btnSpacex">False</button>
</div>
<div className="clearfix" />
<div className="col12 launchYear">
<p className="marg0">Successful Landing</p>
<button
onClick={e => onBtnLandSuccessful(true)}
className="btn btn-default btnSpacex">True</button>
<button
onClick={e => onBtnLandSuccessful(false)}
className="btn btn-default btnSpacex">False</button>
</div>
</div>
</div>
<div className="col-xl-10 col-lg-10 col-md-10 col-sm-10 col-xs-12 items1">
<div className="row">
{product.map(product => (
<div
key={product.flight_number}
className="col-xl-3 col-lg-3 col-md-3 col-sm-3 col-xs-12 marginBottom15"
>
<div className="inner">
<img
src={product.links.mission_patch}
className="full-width imgBg"
alt={product.mission_name}
/>
<div className="clearfix" />
<p className="productName bold margBot5">
{product.mission_name} #{product.flight_number}
</p>
<div className="clearfix" />
<p className="bold margBot5">
Mission Ids:
<ul className="marg0 blueClr">
<li>{product.mission_id}</li>
</ul>
</p>
<div className="clearfix" />
<p className="bold margBot5">
Launch Year:
<span className="normal blueClr">
{product.launch_year}
</span>
</p>
<div className="clearfix" />
<p className="bold margBot5">
Successful Launch:
<span className="normal blueClr">
{product.launch_success}
</span>
</p>
<div className="clearfix" />
<p className="bold margBot5">
Successful Landing:
<span className="normal blueClr">
{product.rocket.first_stage.cores[0].land_success}
</span>
</p>
</div>
</div>
))}
</div>
</div>
</div>
</div>
)
}
export default Product

Sorting an array of objects in ReactJS from an API endpoint

In short: I am working on a Bicycle collection app, where I pull an Array of objects from my endpoint to display on a page. I now want to add the functionality of sorting/filtering the bicycles based on year, brand and size when the user selects a field in the dropdown menu. How do I accomplish that inside by component in react?
Similar to this in the browser: /category?year=2000&size=XL&brand=cervelo, I want to do that from my component when a field in the dropdown is selected.
This is my component:
import React, { Component } from 'react'
import actions from '../../actions'
import { Link } from 'react-router'
import { connect } from 'react-redux'
class Category extends Component {
constructor(){
super()
this.state = {
}
}
componentDidMount(){
this.props.getAllBikes()
}
render(){
return(
<div>
<div className="col-xs-12 col-md-2" style={{paddingTop: 0, paddingRight: '70px', left: '5.5%', top: '-4px'}}>
<aside>
<ul className="nav-coupon-category panel">
<li className="all-cat">
<a className="font-14" href="#">Kategorier:</a>
</li>
<li><i className="fa fa-angle-double-right"></i>Tri Cykler
</li>
<li><i className="fa fa-angle-double-right"></i>Racercykler
</li>
<li><i className="fa fa-angle-double-right"></i>Mountainbikes
</li>
<li><i className="fa fa-angle-double-right"></i>Bane Cykler
</li>
<li><i className="fa fa-angle-double-right"></i>Cross Cykler
</li>
<li><i className="fa fa-angle-double-right"></i>Hverdags Cykler
</li>
<li><i className="fa fa-angle-double-right"></i>Vinter Racercykler
</li>
</ul>
</aside>
</div>
<main id="mainContent" className="main-content">
<div className="page-container ptb-60">
<div className="container">
<div className="contact-area contact-area-v1 panel">
<div className="row row-tb-20">
<div style={{paddingBottom: 0}} className="col-xs-12">
<div className="filter-search">
<div className="row">
<div style={{right: '-30px'}} className="col-6 col-md-3 filter-height">
<div className="right-10 pos-tb-center">
<select style={{width: '232%'}} className="form-control input-sm">
<option>Mærke/Brand</option>
<option>Giant</option>
<option>Trek</option>
<option>Specialized</option>
<option>S-Works</option>
<option>Cannondale</option>
<option>Cervelo</option>
<option>Scott</option>
<option>Bianchi</option>
<option>Canyon</option>
<option>Cube</option>
<option>Pinarello</option>
<option>Fuji</option>
<option>Colnago</option>
<option>Felt</option>
<option>Wilier</option>
<option>BH</option>
</select>
</div>
</div>
<div style={{right: '-13px'}} className="col-6 col-md-3 filter-height">
<div className="right-10 pos-tb-center">
<select style={{width: '324%'}} className="form-control input-sm">
<option>Størrelse</option>
<option>50</option>
<option>52</option>
<option>54</option>
<option>56</option>
<option>58</option>
<option>60</option>
<option>62</option>
</select>
</div>
</div>
<div className="col-6 col-md-3 filter-height">
<div style={{right: '13px'}} className="col-6 col-md-3 filter-height">
<div className="right-10 pos-tb-center">
<select style={{width: '490%'}} className="form-control input-sm">
<option>Årgang</option>
<option>Før</option>
<option>2008</option>
<option>2009</option>
<option>2010</option>
<option>2011</option>
<option>2012</option>
<option>2013</option>
<option>2014</option>
<option>2015</option>
<option>2016</option>
<option>2017</option>
</select>
</div>
</div>
</div>
<div className="col-6 col-md-3 filter-height">
<div style={{right: '31px'}} className="col-6 col-md-3 filter-height">
<div className="right-10 pos-tb-center">
<select style={{width: '494%'}} className="form-control input-sm">
<option>Sorter Efter</option>
<option>Nyeste</option>
<option>Pris: Lav til Høj</option>
<option>Pris: Høj til Lav</option>
</select>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div className="ptb-30 prl-30">
<div className="row row-tb-20">
{(this.props.category == null) ? null :
this.props.category.map((bike, i) => {
return (
<div key={i} className="col-sm-6 col-md-4 col-lg-3">
<div className="coupon-single panel t-center salg-shadow">
<div className="row">
<div className="col-xs-12">
<div className="text-center p-20">
<a href="#">
<img src={bike.attachments[0]}/>
</a>
</div>
</div>
<div style={{maxHeight: '220px', minHeight: '220px'}} className="col-xs-12">
<div className="panel-body">
<ul className="deal-meta list-inline mb-10">
<li style={{textTransform: 'capitalize'}} className="color-muted"><i className="ico fa fa-tag mr-5"></i>{bike.brand}</li>
<li className="color-muted"><i className="ico fa fa-cube mr-5"></i>{bike.size}</li>
<li className="color-muted"><i className="ico fa fa-thumb-tack mr-5"></i>{bike.year}</li>
</ul>
<h4 className="color-green mb-10 t-uppercase">DKK {bike.price}.00</h4>
<h5 className="deal-title mb-10">
{bike.title}
</h5>
<ul className="deal-meta list-inline mb-10">
<li style={{textTransform: 'capitalize'}} className="color-muted"><i className="ico fa fa-map-marker mr-5"></i>{bike.location}</li>
<br/>
<li className="color-muted"><i className="ico fa fa-user-circle mr-5"></i>{bike.name}</li>
</ul>
<div className="showcode">
<button className="btn btn-sm btn block more-info">Vis Mere</button>
<button className="btn btn-sm btn block more-info">Kontakt Info</button>
</div>
</div>
</div>
</div>
</div>
</div>
)
})
}
</div>
</div>
</div>
</div>
</div>
</main>
</div>
)
}
}
const stateToProps = (state) => {
return {
category: state.category.allBikes
}
}
const dispatchToProps = (dispatch) => {
return {
getAllBikes: (bike) => dispatch(actions.getAllBikes(bike))
}
}
export default connect(stateToProps, dispatchToProps)(Category)
If you are using React Router v3 or v2, you can access the query string params from the location.query object that passed to your component.
For example:
<Route path="category" component={Category} />
And then in your Category component, you can do this.props.location.query.year etc...
EDIT
Forgot to mention that react router v4 doesnt support this. you can read about other solution here
EDIT #2
Following you other question in comments:
Given the url you posted:
localhost:3000/category?year=2000&size=XL&brand=cervelo
By accesing this.props.location.query.year will return 2000
and this.props.location.query.brand will return cervelo and so on...

Categories

Resources