run reduce function before map - reactjs

In our scenario , I map the array and produce the result using jsx , but I want the ignore duplicate data before the map operation. so how can I do that? here snipped code may help you :
import React, { useContext } from "react";
import { Context } from "../Context/Context";
import "./Navbar.css"
import cartImg from "../../cart.png"
import close from "../../close.svg"
export default function Navbar() {
const { cart, cartReducer } = useContext(Context)
function getCart(products) {
return products.map((product, index) =>
<div key={index} style={{ borderBottom: "1px solid #d5cfcf" }} >
<img src={product.image} style={{ width: '100%' }} alt="" />
<div className="cart-info">
<div>
<img src={close} onClick={() =>
cartReducer({ product, type: 'remove' })} style={{ width: 30, paddingLeft: 10 }} alt="" />
</div>
<div>
{product.name}
</div>
</div>
</div>
)
}
return (
<nav className="navbar navbar-light bg-light">
<a className="navbar-brand" href="#">
<img src={cartImg} style={{ maxWidth: 30 }} alt="" />
{cart.length > 0 && <span className="badge badge-warning badge-header">{cart.length}</span>}
<div className="navbar-cart" style={cart.length > 0 ? { width: 150 } : { width: 'fit-content' }}>
<h6> {cart.length == 0 ? 'Cart is Empty' : getCart(cart)}</h6>
</div>
</a>
</nav>
)
}

You can remove duplicates by:
const duplicatedData = [1,2,3,4,5,1,2,1,1,1,1,3,4,5,6,7,8,2,1,3,4]
const notDuplicatedData = [...new Set(duplicatedData)]
console.log(notDuplicatedData)
So in your case:
[...new Set(products)].map((product, index)

Related

ReactJS Giving An Unexpected Warning: Each child in a list should have a unique "key" prop

It's a beautiful day but this thing is blocking my view:
I've tried everything (except asking a question ._.) and searched everywhere. But the expected result could not be obtained :'(
So, this is my code where I think the error is happening:
<div className="mt-3">
{data.activities?.map((act) => {
return <Chip className="mr-2 px-3" label={act} key={act.id} />;
})}
</div>{" "}
Well it's a part of my file packageCard.js but if you want the whole file here it is:
import Chip from "#material-ui/core/Chip";
import Clock from "./img/main_page_icons/clock.svg";
import Person from "./img/main_page_icons/person.svg";
import MapPin from "./img/main_page_icons/map-pin.svg";
import Package1 from "./img/main_page/package 1.png";
function PackageCard({ data }) {
console.log(data);
return (
<>
<div className="col-lg-4 col-md-6 col-sm-12 card-super-container">
<div className="card-container">
<div className="card-image-wrapper">
<div>
<div className="card-image-background">
<img
alt="package 1"
src={data.featuredImg}
style={{ borderRadius: "6px" }}
className="w-100 "
/>
</div>
</div>
</div>
<div className="card-details-container">
<span className="text-bold details-container-header">
{data.name}
</span>
<div>
<div className="card-details-text">
<div>{data.description}</div>
<div>
<h6 className="card-price">{`Price: ${data.price} USD`}</h6>
</div>
</div>
</div>
</div>
<div>
<div className="card-final-desc">
<div className="card-final-desc-item">
<span className="card-dot"></span>
<img alt="clock" src={Clock} className="mr-1" />
{` ${data.days}D / ${data.nights}N `}
</div>
<div className="card-final-desc-item">
<span className="card-dot"></span>
<img alt="clock" src={Person} className="mr-1" />
{` ${data.noOfPersons} Person `}
</div>
<div className="card-final-desc-item">
<span className="card-dot"></span>
<img alt="clock" src={MapPin} className="mr-1" />
{` ${data.destination} `}
</div>
</div>
</div>
<div className="card-btn-container">
<button className="btn zoki-btn">Book Now </button>
</div>
</div>
</div>
<div className="col-lg-4 mb-4">
<img
alt="package 1"
src={data.featuredImg}
style={{ height: 250 }}
className="w-100"
/>
<div
className="bg-white py-4 px-4 shadow-lg"
style={{ fontSize: 14, textAlign: "start" }}
>
<h6>{data.name}</h6>
<p>{data.description}</p>
<div className="d-flex justify-content-between w-100">
<h6 className="m-0">{`Price: ${data.price} USD`}</h6>
<h6 className="m-0" style={{ color: "#9C8E35", cursor: "pointer" }}>
Book Now
</h6>
</div>
/!*{" "}
<div className="mt-3">
{data.activities?.map((act) => {
return <Chip className="mr-2 px-3" label={act} key={act.id} />;
})}
</div>{" "}
*!/
</div>
<div
className="row shadow mx-3"
style={{ backgroundColor: "#9C8E35", fontSize: 12 }}
>
<div className="col-4 p-0 text-center">
<div
className="py-2 text-white d-flex w-100 justify-content-center"
style={{ borderRight: "1px solid white" }}
>
<img alt="clock" src={Clock} className="mr-1" />
<p className="mb-0">{` ${data.days} D / ${data.nights} N `}</p>
</div>
</div>
<div className="col-4 p-0">
<div
className="py-2 text-white d-flex w-100 justify-content-center"
style={{ borderRight: "1px solid white" }}
>
<img alt="clock" src={Person} className="mr-1" />
<p className="mb-0">{` ${data.noOfPersons} Person `}</p>
</div>
</div>
<div className="col-4 p-0">
<div className="py-2 text-white d-flex w-100 justify-content-center">
<img alt="clock" src={MapPin} className="mr-1" />
<p className="mb-0">{` ${data.destination} `}</p>
</div>
</div>
</div>
</div>
</>
);
}
export default PackageCard;
Packages.js Component
import { useState, useEffect } from "react";
import { getAvailablePackages } from "crud";
import PackageBg from "../../../assets/img/offers.jpg";
import Card from "./packageCard";
import CircularProgress from "#material-ui/core/CircularProgress";
import { useHistory } from "react-router-dom";
function Packages() {
const history = useHistory();
const [listPackages, setListPackages] = useState([]);
const [loading, setLoading] = useState(false);
useEffect(() => {
const params = {
search: { query: "" },
sort: "name",
page: 1,
pageSize: 3,
};
setLoading(true);
getAvailablePackages(params)
.then((res) => {
// console.log(res.data.data)
setListPackages(res.data.data.travelPackages);
setLoading(false);
})
.catch((error) => {
console.log(error.response.data);
console.log(error.response.status);
setLoading(false);
});
}, []);
let checkData = [
{
name: "ahmad",
description: "this is description",
price: 5,
days: 5,
nights: 9,
noOfPersons: 9,
destination: "England",
featuredImg:
"https://media.gettyimages.com/photos/castle-combe-in-the-fall-wiltshire-england-picture-id157006201?s=612x612",
},
{
name: "ali",
description: "this is description",
price: 5,
days: 5,
nights: 9,
noOfPersons: 9,
destination: "homeland",
featuredImg:
"https://images.unsplash.com/photo-1538332576228-eb5b4c4de6f5?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8Mnx8ZmlubGFuZHxlbnwwfHwwfHw%3D&w=1000&q=80",
},
{
name: "ali",
description: "this is description",
price: 5,
days: 5,
nights: 9,
noOfPersons: 9,
destination: "finland",
featuredImg:
"https://images.unsplash.com/photo-1538332576228-eb5b4c4de6f5?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8Mnx8ZmlubGFuZHxlbnwwfHwwfHw%3D&w=1000&q=80",
},
];
return (
<div
id="zoki-packages"
className="text-center py-5 my-5"
style={{
backgroundImage: `url(${PackageBg})`,
backgroundPosition: "center",
backgroundSize: "cover",
}}
>
<div className="container" style={{ color: "#344767" }}>
<h6 className="text-bold font-italic"> EXPLORE GREAT PLACES </h6>
<h1 className=""> Popular Packages </h1>
<div className="row justify-content-center align-content-center">
{checkData?.map((pkg) => {
return <Card data={pkg} key={pkg.id} />;
})}
{loading ? (
<CircularProgress className="my-4 ml-auto mr-auto" />
) : listPackages.length ? (
listPackages?.map((pkg) => {
return <Card data={pkg} key={pkg.id} />;
})
) : (
<h4 className="my-4 ml-auto mr-auto">
No Package Available at that time.
</h4>
)}
</div>
{listPackages.length ? (
<button
onClick={() => history.push("/search-packages")}
className="btn btn-dark px-4 p-2 rounded-pill my-4"
style={{ color: "#CFBD45", backgroundColor: "black", fontSize: 14 }}
>
<p className="mb-0"> VEIW ALL PACKAGES </p>
</button>
) : null}
</div>
</div>
);
}
export default Packages;
I will be very grateful if you find a solution. I appreciate any help you can provide <33
It seems that the act does not have a unique id, try using the index of the map.
<div className="mt-3">
{data.activities?.map((act, i) => (
<Chip className="mr-2 px-3" label={act} key={i} />
))}
</div>
if you use the act.id as the key,should make sure every id is unique cause
Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity
here is the official docs

How to close only one Div at a time in React?

Code:-
const [Close, setClose] = useState(true)
<div className="allDivs">
{item.map((item, index) => {
// console.log("myDivs", myDivs);
return (
<Fragment key={index} >
<div className="tableHeaderBody" id="CLOSEDIV" style={{display: Close ? 'initial' : 'none'}}>
<div className="TableText">
<div className="TableTextHide"></div> <div style={{ color: "white" }} id="SHOW">{item.val}</div></div>
<div className="CloseIcon" id="CloseBtn"><FaCircle style={{ color: "#FC0000", width: "10px", height: "10px", alignItems: "right" }} onClick={() => setClose(false)} /></div>
</div>
</Fragment>
)
})
}
</div>
I want that when i click the Red circle at any div (show in image) it close the div, but right now when i click the One div red circle its closes all the div
please help.
Try this:
Create a new component ChildComponent:
export default function ChildComponent({item}) {
const [Close, setClose] = useState(true) // Every Child now has it's own setClose controll
return (
<Fragment>
<div className="tableHeaderBody" id="CLOSEDIV" style={{display: Close ? 'initial' : 'none'}}>
<div className="TableText">
<div className="TableTextHide"></div>
<div style={{ color: "white" }} id="SHOW">{item.val}</div>
</div>
<div className="CloseIcon" id="CloseBtn">
<FaCircle style={{ color: "#FC0000", width: "10px", height: "10px", alignItems: "right" }} onClick={() => setClose(false)} />
</div>
</div>
</Fragment>
)
}
Pass the ChildComponent to your component shown above:
<div className="allDivs">
{item.map((item, index) => (
<div key={index}>
<ChildComponent item={item} />
</div>
))}
</div>

Only 1 card is displaying on screen instead or 4 cards in row react and antd. Help I'm new at this

I'm using antd and little bit of bootstrap. please find the fault. I'm making this project from this video - https://www.youtube.com/watch?v=VihRQ_uhHtE&t=1915s . all the files for this movie page is shown below.
Here is the main page landingcomponent.js
import React, { useEffect, useState } from 'react';
import axios from 'axios';
import {API_URL, API_KEY, IMAGE_URL} from '../../config/keys';
import {Typography, Row} from 'antd';
import MainImage from './MainImage';
import GridCard from './GridCard';
const {Title} = Typography;
function LandingPage() {
const [Movies, setMovies] = useState([])
useEffect( () => {
fetch(`${API_URL}movie/popular?api_key=${API_KEY}&language=en-US&page=1`)
.then(response => response.json())
.then(response => {
console.log(response);
setMovies(response.results);
})
}, [])
return(
<div style={{width:'100%'}}>
{Movies[0] &&
<MainImage image={`${IMAGE_URL}original${Movies[0].backdrop_path}`}
title={Movies[0].original_title}
text={Movies[0].overview} />}
<div className= "m-2">
<Title className='font-weight-bolder' style={{ color: 'black' }}>Latest Movies</Title>
<div>
<Row gutter={[16,16]}>
{Movies && Movies.map((movie, index) => (
<React.Fragment key={index}>
<GridCard
image={movie.poster_path && `${IMAGE_URL}original${movie.poster_path}`}
movieId={movie.id}
/>
</React.Fragment>
))}
</Row>
<div className="text-center">
<button className="btn btn-primary" onClick>Load More</button>
</div>
</div>
</div>
</div>
);
}
export default LandingPage;
and this is my gridcard.js file
import React from 'react';
import {Col} from 'antd'
function GridCard(props) {
return (
<Col lg={6} md={8} xs={24}>
<div className="position-relative">
<a href={`/movie/${props.movieId}`}>
<img style={{ width:'100%', height:'300px'}} alt="image" src={props.image} />
</a>
</div>
</Col>
)
}
export default GridCard;
also last MainImage.js file
import React from 'react';
import {Typography, Row} from 'antd';
const {Title} = Typography;
function MainImage(props) {
return(
<div className="img-responsive position-relative"
style={{
background: `url('${props.image}'), #1c1e1c`,
backgroundPosition: 'center',
backgroundSize: 'cover',
height: '50vh',
backgroundRepeat: 'no-repeat',
width: '100%',
}}
>
<div>
<div className='position-absolute' style={{ maxWidth:'450px', bottom: '2rem', marginLeft: '2rem' }} >
<Title className='h1' level={2}> {props.title} </Title>
<p style={{ color: 'white', fontSize: '1rem' }} > {props.text} </p>
</div>
</div>
</div>
);
}
export default MainImage;

Button/dropdown button disabled by default without specifying disabled

I am trying to add a dropdown button in my react project and its rendering as disabled by default. why is this happening ?
The first dropdown is working fine, i called the same dropdown in the navbar after this one and it renders as disabled. I tried other things as well, like adding a button also would not work for me.
The navbar is diplayed when i get a response from the backend and a different component is rendered (ResultTable)
import React from "react";
import ResultTable from "./ResultTable";
...
import DropdownButton from "react-bootstrap/DropdownButton";
import Dropdown from "react-bootstrap/Dropdown";
class MainContainer extends React.Component {
constructor(props) {
super(props);
this.state = {
//more state values
threshold: 0.75
};
this.thresholdChange = this.thresholdChange.bind(this);
}
thresholdChange(input) {
this.setState({
threshold: input
});
}
toProperCase = function (txt) {
return txt.replace(/\w\S*/g, function (txt) { return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); });
};
render() {
const { responseData } = this.state;
return (
<div className="container-flex container-without-scroll wrapper"
style={{
backgroundImage: `url(${bg})`,
width: "100%",
height: "100vh",
backgroundSize: "cover",
backgroundRepeat: "no-repeat",
overFlow:'hidden'
}}
>
<div
className={`container-fluid `}>
{this.state.displayTable ? (
<Navbar
style={{
position: "fixed",
left: "50%",
top: "95%",
transform: "translate(-50%, -90%)",
backgroundColor: 'black'
}}
sticky="bottom"
>
<br />
<Navbar.Collapse className="justify-content-end">
<Button
variant="primary"
disabled={
this.props.initialTransaction &&
this.props.initialTransaction.version == 0 &&
this.props.initialTransaction
? true
: false
}
size="sm"
style={{ color: "#FFF" }}
onClick={this.undoAction}
>
<span className=" fa fa-undo "></span>
Undo
</Button>
<Button
variant="primary"
size="sm"
style={{ color: "#FFF" }}
disabled={
(this.props.initialTransaction &&
this.props.initialTransaction.version) <
(this.props.currentVersion &&
this.props.currentVersion.version)
? false
: true
}
onClick={this.redoAction}
>
<span className=" fa fa-repeat "></span>
Redo
</Button>
<Button
variant="success"
size="sm"
style={{ color: "#FFF" }}
disabled={
this.props.initialTransaction &&
this.props.initialTransaction.version == 0
? true
: false
}
onClick={() =>
this.exportExcel(this.props.initialTransaction)
}
>
<span className=" fa fa-download "></span>
Export
</Button>
<DropdownButton
size="md"
title={this.state.threshold}
>
{this.state.thresholdValues.map(eachValue => {
return (
<Dropdown.Item
key = {Math.random()}
onClick={() => this.thresholdChange(eachValue)}
as="button"
>
{eachValue}
</Dropdown.Item>
);
})}
</DropdownButton>
</Navbar.Collapse>
<br/>
</Navbar>
) : null}
{this.state.displayTable ? null : (
<div
className="col-md-4 col-md-offset-4"
style={{
position: "absolute",
left: "50%",
top: "50%",
transform: "translate(-50%, -50%)",
backgroundColor: 'rgba(14, 13, 13, 0.74)'
}}
>
<br />
<div className="row">
<div className="input-group col-md-9">
<div className="input-group-prepend">
<span
style={{ cursor: 'pointer' }}
onClick={this.onFormSubmit}
className="input-group-text"
id="inputGroupFileAddon01"
>
{" "}
Upload{" "}
</span>
</div>
<div className="custom-file">
<input
type="file"
className="custom-file-input"
id="inputGroupFile01"
onChange={this.onChange}
aria-describedby="inputGroupFileAddon01"
/>
<label
className="custom-file-label"
htmlFor="inputGroupFile01"
>
{this.props.active && this.props.active.filename}
</label>
</div>
</div>
<div className="col-md-3">
<DropdownButton
size="md"
id="dropdown-item-button"
title={this.state.threshold}
>
{this.state.thresholdValues.map(eachValue => {
return (
<Dropdown.Item
onClick={() => this.thresholdChange(eachValue)}
as="button"
>
{eachValue}
</Dropdown.Item>
);
})}
</DropdownButton>
</div>
</div>
<br />
</div>
)}
<div >
{this.state.displayTable ? (
<div className = "container-flex" style =
{{overflowY:'scroll', maxHeight:'80vh'}}>
<ResultTable
data={responseData}
afterMerge={params => {
this.afterMerge(params);
}}
/>
</div>
) : null}
</div>
</div>
</div>
);
}
}
// Maps state from store to props
const mapStateToProps = (state, ownProps) => {
return {
};
};
// Maps actions to props
const mapDispatchToProps = dispatch => {
return {
};
};
// Use connect to put them together
export default connect(
mapStateToProps,
mapDispatchToProps
)(MainContainer);

How do I convert an array of col-sm-3 columns into rows with 4 columns each?

I have the below code and I'm trying to figure out how to convert the mapped array of categories into rows with four categories in each.
renderCategories = () => {
const categories = this.state.categories.map( category => {
return (
<div key={ category.categoryId} className="col-sm-3 card text- center" style={{margin: '10px', paddingTop: '5px'}}>
<h5>
<Link to={ `/category/${ category.categoryId }`}>{ category.name }</Link>
</h5>
</div>
)
});
return categories;
};
You need to wrap renderCategories into div with class "row"
renderCategories = () => {
const categories = this.state.categories.map( category => {
return (
<div key={ category.categoryId} className="col-sm-3 card text- center" style={{margin: '10px', paddingTop: '5px'}}>
<h5>
<Link to={ `/category/${ category.categoryId }`}>{ category.name }</Link>
</h5>
</div>
)
});
return <div class="row">{categories}</div>;
};
To create a new row on every 4 columns, you could add a conditional statement like below :
renderCategories = () => {
let categories = [];
this.state.categories.forEach((category, i) => {
if((i+1) % 4 == 0){
categories.push(
<div className="row" key={category.categoryId}>
<div key={category.categoryId} className="col-sm-3 card text- center" style={{ margin: '10px', paddingTop: '5px' }}>
<h5>
<Link to={`/category/${category.categoryId}`}>{category.name}</Link>
</h5>
</div>
</div>
)
}else{
categories.push(
<div key={category.categoryId} className="col-sm-3 card text- center" style={{ margin: '10px', paddingTop: '5px' }}>
<h5>
<Link to={`/category/${category.categoryId}`}>{category.name}</Link>
</h5>
</div>
);
}
});
return categories;
}
Or alternatively you could still using the whole columns in a single row by inserting a
<div className="clearfix"></div> on every 4 item to force the columns to wrap :
render() {
let categories = [];
this.state.categories.forEach((category, i) => {
categories.push(
<div key={category.categoryId} className="col-sm-3 card text- center" style={{ margin: '10px', paddingTop: '5px' }}>
<h5>
<Link to={`/category/${category.categoryId}`}>{category.name}</Link>
</h5>
</div>
);
// insert full width div every 4 columns
if ((idx + 1) % 4 === 0) { categories.push(<div className="clearfix"></div>) }
});
return categories;
}

Resources