React js ecommerce price change when size and material variants option selected - javascript

I am trying to get the final price in the productInfo page when the material and size variants options are selected.
In the data.js:
export const productItems = [
{
id: 1,
image: ["../Images/Prod1/Swiming_fish_W.png","../Images/Prod1/Ocean Fish2.png"],
title: "Swim Fish",
price:49.99,
desc: "Simplicty, Naturality, and Humanity of Art",
variants: [{material: "Stretched Canvas", size: "12x16 inches", price: 49},
{material: "Stretched Canvas", size: "15x20 inches", price: 69},
{material: "Fine Art Print", size: "12x16 inches", price:39},
{material: "Fine Art Print", size: "15x20 inches", price: 59},
],
},
{
id: 2,
image: ["../Images/Prod2/Duckling_W.png","../Images/Prod2/Duckling 2.png"],
title: "Bath Duckling",
price:49.99,
desc: "Simplicty, Naturality, and Humanity of Art",
variants: [{material: "Stretched Canvas",size: "20x24 inches", price: 69},
{material: "Stretched Canvas",size: "24x30 inches", price: 79},
{material: "Fine Art Print", size: "20x24 inches", price:59},
{material: "Fine Art Print", size: "24x30 inches", price: 69},
],
}]
In the detailProductPage.js
import React, { useEffect, useState } from 'react';
// import { Col, Row } from 'antd';
import ProductImages from './ProductImages';
import ProductInfo from './ProductInfo';
import {productItems} from '../Data';
import { useParams } from 'react-router-dom';
import './DetailProductPage.css';
function DetailProductPage() {
const { id }=useParams();
const [details, setDetails]=useState([])
useEffect(() => {
setDetails(productItems.find(item => String(item.id) ===id ))
}, [id]);
return (
<div className="postPage" style={{width:'100%', padding: '5rem 3rem'}}>
<div className="detailInfo">
<div className="detailLeft">
<ProductImages detail={details} />
</div>
<div className="detailRight">
<ProductInfo detail={details} />
</div>
</div>
</div>
)
}
export default DetailProductPage
Finally in the ProductInfo.js
import React, {useEffect, useState} from 'react';
import { useStateValue } from '../StateProvider';
import './ProductInfo.css';
import Select from 'react-select';
function ProductInfo(props) {
const [Product, setProduct] = useState({})
const [{basket},dispatch]=useStateValue()
const [size, setSize] = React.useState();
const [material, setMaterial] = React.useState();
const [price, setPrice] = React.useState();
console.log(props.detail.variants)
const materialOptions = props.detail.variants
.map((p) => p.material)
.filter((v, i, a) => a.indexOf(v) === i)
.map((material) => ({ label: material, value: material }))
console.log(materialOptions)
const sizeOptions = props.detail.variants
.map((p) => p.size)
.filter((v, i, a) => a.indexOf(v) === i)
.map((size) => ({ label: size, value: size }));
console.log(sizeOptions)
const priceOptions = props.detail.variants
.filter((p) => size && p.size === size.value && material && p.material=== material.value)
.map((p) => p.price)
.filter((v, i, a) => a.indexOf(v) === i)
.map((price) => ({ label: price, value: price }));
console.log(priceOptions.length)
useEffect(()=>{
setProduct(props.detail)
}, [props.detail])
return (
<div className='prod__info'>
<h1>{Product.title}</h1>
<h5 className='prod__desc'>Description</h5>
<p className='prod__text'>{Product.desc}</p>
<p className='prod__price'>
<small>$</small>
if (priceOptions.length===1){
priceOptions.value
} else {Product.price}
</p>
<br />
<p className='prod__desc'>Material</p>
<div style={{boxShadow: '0 5px 5px #939596',cursor:'pointer',borderRadius: '10px!'}}>
<Select value={material} onChange={setMaterial} options={materialOptions} />
</div>
<p className='prod__desc'>Size</p>
<div style={{boxShadow: '0 5px 5px #939596',cursor:'pointer',borderRadius: '10px!'}}>
<Select value={size} onChange={setSize} options={sizeOptions} />
</div>
<br />
<br />
<div className='button__cart'>
<button className='prod__button'
onClick={addToBasket}
>
Add to basket
</button>
</div>
</div>
)
}
export default ProductInfo
I have problems in getting the final price change after material and size variant options selected in ProductInfo.js
<p className='prod__price'>
<small>$</small>
if (priceOptions.length===1){
priceOptions.value
} else {Product.price}
</p>
For reference, my website is weiwhite.com, clicking on one of the painting for the product detail page.

In productInfo.js add a ? in front of .map:
//...
let finalPrice={}
if (priceOptions?.length === 1) {
finalPrice = priceOptions.value
} else {
finalPrice = Product.price
}
//...
return
//...
<strong> finalPrice </strong>
//...
The question mark creates an Optional Chain.
The optional chaining operator (?.) enables you to read the value of a property located deep within a chain of connected objects without having to check that each reference in the chain is valid. - MDN

Related

Image is not showing in React app using img tag

My image is not showing in React app. I am trying to fetch the path from JSON and pass the path using props in <img> tag.
Example JSON object with the product data:
let data = [
{
id: 1,
name: "Striped Slim Fit Shirt",
image: "./Assets/m1.jpg",
price: 1000,
category: "Men",
size: "XL",
inStock: true,
},
{
id: 2,
name: "Full Sleeves Slim Fit Shirt",
image: "./Assets/m2.jpg",
price: 2000,
category: "Men",
size: "L",
inStock: true,
},
];
export default data;
My parent component from which I am passing props.
import { Fragment } from "react";
import data from "../../DUMMY_DATA";
import ItemList from "./ItemList";
const HomePage = () => {
const availableItems = data.map((products) => (
<ItemList
key={products.id}
images={products.image}
name={products.name}
price={products.price}
category={products.category}
size={products.size}
/>
));
return (
<Fragment>
<div>{availableItems}</div>
</Fragment>
);
};
export default HomePage;
My child component. Here, console logging shows the correct path, but the <img> tag is not rendering it.
import { Fragment } from "react";
const ItemList = (props) => {
const { id, images, name, price, category, size, inStock } = props;
return (
<Fragment>
<div className="container text-center">
<div className="row row-cols-4" key={id}>
<div className="col">
<img src={images} />
</div>
<div className="col">{name}</div>
<div className="col">{size}</div>
<div className="col">{price}</div>
</div>
</div>
</Fragment>
);
};
export default ItemList;

Redux with redux toolkit: UI is not changing

I'm new to redux and redux toolkit in React.js. Trying my best to make my PET project to apply for a future job, but faced a problem. I'll try to describe it.
Firstly, the code. removeInvoice function in invoice-slice.js file:
import { createSlice } from "#reduxjs/toolkit";
import { INVOICES_LIST } from "../Pages/Invoice/InvoicesList";
const invoiceSlice = createSlice({
name: "invoice",
initialState: {
invoices: INVOICES_LIST,
},
reducers: {
addNewInvoice(state, action) {
const newItem = action.payload;
state.invoices.push({
id: newItem.id,
billFrom: newItem.bill_from,
billFromAddress: newItem.billFromAddress,
billTo: newItem.bill_to,
billToAddress: newItem.bill_to_address,
invoiceNumber: newItem.invoice_num,
});
console.log(newItem);
},
removeInvoice(state, action) {
const id = action.payload;
state.invoices = state.invoices.filter((item) => item.id !== id);
console.log(action);
console.log(state.invoices);
},
editInvoice() {},
},
});
export const invoiceActions = invoiceSlice.actions;
export default invoiceSlice;
INVOICES_LIST looks like this:
export const INVOICES_LIST = [
{
id: Math.random().toString(),
number: Math.random().toFixed(2),
invoice_num: "#1232",
bill_from: "Pineapple Inc.",
bill_to: "REDQ Inc.",
total_cost: "14630",
status: "Pending",
order_date: "February 17th 2018",
bill_from_email: "pineapple#company.com",
bill_from_address: "86781 547th Ave, Osmond, NE, 68765",
bill_from_phone: "+(402) 748-3970",
bill_from_fax: "",
bill_to_email: "redq#company.com",
bill_to_address: "405 Mulberry Rd, Mc Grady, NC, 28649",
bill_to_phone: "+(740) 927-9284",
bill_to_fax: "+0(863) 228-7064",
ITEMS: {
item_name: "A box of happiness",
unit_costs: "200",
unit: "14",
price: "2800",
sub_total: "133300",
vat: "13300",
grand_total: "14630",
},
},
{
id: Math.random().toString(),
number: Math.random().toFixed(2),
invoice_num: "#1232",
bill_from: "AMD Inc.",
bill_to: "Intel Inc.",
total_cost: "14630",
status: "Delivered",
order_date: "February 17th 2018",
bill_from_email: "pineapple#company.com",
bill_from_address: "86781 547th Ave, Osmond, NE, 68765",
bill_from_phone: "+(402) 748-3970",
bill_from_fax: "",
bill_to_email: "redq#company.com",
bill_to_address: "405 Mulberry Rd, Mc Grady, NC, 28649",
bill_to_phone: "+(740) 927-9284",
bill_to_fax: "+0(863) 228-7064",
ITEMS: {
item_name: "Unicorn Tears",
unit_costs: "500",
unit: "14",
price: "1700",
sub_total: "133300",
vat: "13300",
grand_total: "14630",
},
},
{
id: Math.random().toString(),
number: Math.random().toFixed(2),
invoice_num: "#1232",
bill_from: "Apple Inc.",
bill_to: "Samsung",
total_cost: "14630",
status: "Shipped",
order_date: "February 17th 2018",
bill_from_email: "pineapple#company.com",
bill_from_address: "86781 547th Ave, Osmond, NE, 68765",
bill_from_phone: "+(402) 748-3970",
bill_from_fax: "",
bill_to_email: "redq#company.com",
bill_to_address: "405 Mulberry Rd, Mc Grady, NC, 28649",
bill_to_phone: "+(740) 927-9284",
bill_to_fax: "+0(863) 228-7064",
ITEMS: {
item_name: "Rainbow Machine",
unit_costs: "700",
unit: "5",
price: "3500",
sub_total: "133300",
vat: "13300",
grand_total: "14630",
},
},
];
AllInvoices.js file where i map invoices:
import React, { Fragment } from "react";
import { useDispatch, useSelector } from "react-redux";
import { uiActions } from "../../store/ui-slice";
// import { invoiceActions } from "../../store/invoice-slice";
import { INVOICES_LIST } from "../Invoice/InvoicesList";
import Wrapper from "../../UI/Wrapper";
import Card from "../../UI/Card";
import Footer from "../../UI/Footer";
import Button from "../../UI/Button";
// import InvoiceItemDescription from "./InvoiceItemDescription";
// import EditInvoiceItem from "./EditInvoiceItem";
import classes from "./AllInvoices.module.css";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import { faChevronDown } from "#fortawesome/free-solid-svg-icons";
// import AddInvoiceItem from "./AddInvoiceItem";
import { Link } from "react-router-dom";
import Invoice from "./Invoice";
const AllInvoices = (props) => {
// const { id } = props;
const dispatch = useDispatch();
const toggleSelectOptions = () => {
dispatch(uiActions.toggleSelectOptions());
};
// const removeInvoiceItem = (id) => {
// dispatch(invoiceActions.removeInvoice(id));
// };
const showMoreOptions = useSelector(
(state) => state.ui.selectOptionsIsVisible
);
// const invoice = useSelector((state) => state.invoices);
return (
<Fragment>
<Wrapper isShrinked={props.isShrinked}>
<Card>
<h1 className={classes.header}>Invoice</h1>
<div className={classes.content}>
<div className={classes["btn-wrapper"]}>
<Link to="/invoices/add-invoice">
<Button>Add Invoice</Button>
</Link>
</div>
<div className={classes.invoices}>
{showMoreOptions && (
<ul className={classes.list}>
<li>Select all invoices</li>
<li>Unselect all</li>
<li>Delete selected</li>
</ul>
)}
<table>
<colgroup>
<col className={classes.col1}></col>
<col className={classes.col2}></col>
<col className={classes.col3}></col>
<col className={classes.col4}></col>
<col className={classes.col5}></col>
<col className={classes.col6}></col>
<col className={classes.col7}></col>
</colgroup>
<thead className={classes["table-head"]}>
<tr>
<th className={classes.position}>
<span className={classes.checkbox}>
<input type="checkbox"></input>
</span>
<FontAwesomeIcon
icon={faChevronDown}
className={classes.chevron}
onClick={toggleSelectOptions}
/>
</th>
<th>
<span className={classes["thead-text"]}>Number</span>
</th>
<th>
<span className={classes["thead-text"]}>Bill From</span>
</th>
<th>
<span className={classes["thead-text"]}>Bill To</span>
</th>
<th>
<span className={classes["thead-text"]}>Total Cost</span>
</th>
<th>
<span className={classes["thead-text"]}>Status</span>
</th>
</tr>
</thead>
<tbody>
{INVOICES_LIST.map((invoice, index) => (
<Invoice
key={index}
invoiceItem={{
id: invoice.id,
invoice_num: invoice.invoice_num,
bill_from: invoice.bill_from,
bill_to: invoice.bill_to,
status: invoice.status,
}}
/>
))}
</tbody>
</table>
</div>
</div>
</Card>
<Footer />
</Wrapper>
</Fragment>
);
};
export default AllInvoices;
And Invoice.js file where i should use removeInvoice:
import React from "react";
import classes from "./Invoice.module.css";
import { useDispatch } from "react-redux";
import { Link } from "react-router-dom";
import { invoiceActions } from "../../store/invoice-slice";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import { faTrash } from "#fortawesome/free-solid-svg-icons";
const Invoice = (props) => {
const { id, invoice_num, bill_from, bill_to, status } = props.invoiceItem;
const dispatch = useDispatch();
const removeInvoiceItem = () => {
dispatch(invoiceActions.removeInvoice(id));
};
return (
<tr className={classes.height}>
<td>
<span className={classes.checkbox}>
<input type="checkbox"></input>
</span>
</td>
<td>
<span>{invoice_num}</span>
</td>
<td>
<span>{bill_from}</span>
</td>
<td>
<span>{bill_to}</span>
</td>
<td>
<span>14300</span>
{/* This should be a dynamic value later */}
</td>
<td>
<span
className={`${
status === "Pending" ? classes["status-pending"] : ""
} ${status === "Delivered" ? classes["status-delivered"] : ""} ${
status === "Shipped" ? classes["status-shipped"] : ""
}`}
>
{status}
</span>
</td>
<td>
<div className={classes.buttons}>
<Link to={`/invoices/invoice-description/${id}`}>
<button className={classes["view-btn"]}>View</button>
</Link>
<button className={classes["delete-btn"]} onClick={removeInvoiceItem}>
<FontAwesomeIcon icon={faTrash} />
</button>
</div>
</td>
</tr>
);
};
export default Invoice;
Now, the issue. It seems to remove the invoice from an array, because array changes from 3 items to 2, and shows in a console payload with appropriate id of item which i wanted to remove by clicking on a button, but UI console.log here doesn't reflect the changes, there is still 3 invoice items instead of 2 or less. Anyone know what can be the problem?
I've already tried alot of variants, like to pass an id to a function like this:
const removeInvoiceItem = (id) => {
dispatch(invoiceActions.removeInvoice(id));
};
Tried to make it with curly braces:
const removeInvoiceItem = (id) => {
dispatch(invoiceActions.removeInvoice({ id }));
};
Also tried anonymous function here:
<button className={classes["delete-btn"]} onClick={() => removeInvoiceItem(id)}>
<FontAwesomeIcon icon={faTrash} />
</button>
And so on. I know that if UI doesn't change, then state is not changing, but, in my case, i overwrite the state like this:
state.invoices = state.invoices.filter((item) => item.id !== id);
So, i don't know what else to do. Thought of useSelector and tried it like this:
const invoice = useSelector((state) => state.invoices);
And in map function:
{invoice.map((invoice, index) => (
<Invoice
key={index}
invoiceItem={{
id: invoice.id,
invoice_num: invoice.invoice_num,
bill_from: invoice.bill_from,
bill_to: invoice.bill_to,
status: invoice.status,
}}
/>
))}
But it was crashing the page and telling me this error: Uncaught TypeError: invoice.map is not a function.
So, i don't know what to do else. Please, help me!!!
P.s. I'm new in stackoveflow, so sorry if something wrong :)
The problem is that you're using the constant INVOICE_LIST to map your elements instead of the current state of the store.
You used INVOICE_LIST to initialize your slice, that's good. But then you did not use what you initialized, you simply used the constant, and that's why the UI remained constant.
You should use useSelector to access that state like so:
const invoiceList = useSelector(state => state.invoice.invoices)
This should be the correct syntaxe in your case:
state.sliceName.wantedProperty
Now when you map on "invoiceList" instead of "INVOICE_LIST", this should do the trick!
You aren't rerendering the INVOICE_LIST when it changes. You would want to have a useEffect or something similar that will rerender the component when the INVOICE_LIST changes to see any changes on the UI side.
Your problem is this:
{INVOICES_LIST.map((invoice, index) => (
<Invoice
key={index}
invoiceItem={{
id: invoice.id,
invoice_num: invoice.invoice_num,
bill_from: invoice.bill_from,
bill_to: invoice.bill_to,
status: invoice.status,
}}
/>
))}
This is rendering static content and will not change even when you make a change to the redux store. You need to change this to state that will rerender when it changes.

How do i use props & map function to insert image urls for cards with logos using React?

I am working on a personal project where NFL Data is displayed by team. I am just learning React and would like to know how to use props and map image urls from an array to display multiple NFL logo cards. I have made a similar website using strictly css, html, and javascript but need to do it in react, anyways, this is what I have:
Home.js
import React from "react"
import { Link} from "react-router-dom"
import Box from '#material-ui/core/Box';
const teams = [
{
id: 1,
teamName: "Kansas City Cheifs",
urlImage: "public/chiefs_logo.jpg"
},
{
id: 2,
teamName: "Cincinatti Bengals",
urlImage: "public/Bengals.jpg"
},
{
id: 3,
teamName: "Denver Broncos",
urlImage: "public/Denver-Broncos-symbol.jpeg"
},
{
id: 4,
teamName: "Carolina Panthers",
urlImage: "public/panthers.png"
}
];
export default function Home(props) {
return (
<div className="Team-Box">
const teamCards = teams.map(team => )
<Box className="Box" key={teams.id} background-image={props.urlImage}/>
<Box className="Box" background-image={props.urlImage}/>
<Link to="/Home"></Link>
</div>
)
}
What it looks like so far
[What I want it to look like][2]
[2]: https://i.stack.imgur.com/KK0tw.jpg, except for all 32 NFL teams
Inside of your return you want something like this.
return (
<div>
{teams.map((team) => (
<div key={team.id} className='Team-Box'>
<Box
className='Box'
style={{ backgroundImage: `url(${team.imageUrl})` }}
/>
</div>
))}
<Link to='/Home'></Link>
</div>
);
Here is an idea of what this would look like if you wanted to pass some data as props to a Card component responsible for displaying the information on each team.
import { useState } from 'react';
const initialTeams = [
{
id: 1,
teamName: 'Kansas City Chiefs',
urlImage: 'public/chiefs_logo.jpg',
},
{
id: 2,
teamName: 'Cincinatti Bengals',
urlImage: 'public/Bengals.jpg',
},
{
id: 3,
teamName: 'Denver Broncos',
urlImage: 'public/Denver-Broncos-symbol.jpeg',
},
{
id: 4,
teamName: 'Carolina Panthers',
urlImage: 'public/panthers.png',
},
];
const Card = ({ imageUrl, teamName }) => (
<div className='team-card' style={{ backgroundImage: `url(${imageUrl})` }}>
{teamName}
</div>
);
const Home = () => {
const [teams, setTeams] = useState(initialTeams);
return (
<div>
{teams.map(({ id, imageUrl, teamName }) => (
<Card key={id} imageUrl={imageUrl} teamName={teamName} />
))}
</div>
);
};
export default Home;

React JS: TypeError: Cannot convert undefined or null to object

I have a Beach component here that is throwing me the error:
TypeError: Cannot convert undefined or null to object
ResortDetail
C:/Users/JS/Desktop/MERN/KR/frontend/src/screens/Beach.js:33
30 | <p>{description}</p>
31 | <br/>
32 | <h4>Amenities:</h4>
> 33 | <div>
| ^ 34 | {
35 | Object.entries(amenities).map(
36 | ([key, value]) => {
View compiled
▶ 17 stack frames were collapsed.
Basically the data looks something like this:
{_id: "2", name: "Bluewater Maribago Beach Resort", price_per_night: 4156,…}
address: "Buyong"
amenities: {tv: true, reservation: true}
city: "New York"
description: "Set in a complex of thatch-roofed buildings on the Cebu Strait, this posh beachfront resort is 1 km from Mactan Island Aquarium and 4 km from the Magellan Shrine."
email: "info#example.com"
image: "https://images.unsplash.com/photo-1507525428034-b723cf961d3e"
latitude: 10.290899
longitude: 124.000822
name: "Bluewater Maribago Beach Resort"
phone: "(032) 402 4100"
price_per_night: 4156
province: "California Road"
rating: 3.5
reviews: 35
website: "http://www.bluewater.us/"
zip_code: "6015"
_id: "2"
I think its complaining about the Object.entries(amenities).map( but not sure why and how can I fix it.
Here's the complete code:
import React, { useState, useEffect } from 'react'
import axios from 'axios'
const Beach = ({ match }) => {
const [resort, setResort] = useState({})
useEffect(() => {
const fetchBeach = async () => {
const { data } = await axios.get(`/api/resorts/${match.params.id}`)
setResort(data)
}
fetchBeach()
}, [match])
const { name, address, city, province, zip_code, image, description, amenities, website, phone, email } = resort
return (
<div className="row mt-5">
<div className="col-lg-7">
<h1>{name}</h1>
<p><FaMapMarkerAlt /> {`${address}, ${city} ${province}, USA, ${zip_code}`}</p>
<img src={image} alt={name} width="700" />
<br/>
<p>{description}</p>
<br/>
<h4>Amenities:</h4>
<div>
{
Object.entries(amenities).map(
([key, value]) => {
if(value){
return <p>{key}</p>
}
return null
}
)
}
</div>
</div>
</div>
)
}
export default Beach
Any idea how to fix this and pull to properly up the object amenities?
The 'amenities' is undefined in the beginning as it takes some time to fetch the data from your API. So your code ends up being Object.entries(null) and hence the error.
Place a check if amenities is not null before you use Object.entires() as shown below.
amenities && Object.entries(amenities).map(
([key, value]) => {
if(value){
return <p>{key}</p>
}
return null
}
)
}
Hope it helps ! :))
import React, { useState, useEffect } from "react";
import axios from "axios";
const Beach = ({ match }) => {
const [resort, setResort] = useState(null);
useEffect(() => {
const fetchBeach = async () => {
const { data } = await axios.get(`/api/resorts/${match.params.id}`);
setResort(data);
};
fetchBeach();
}, [match]);
const {
name,
address,
city,
province,
zip_code,
image,
description,
amenities,
website,
phone,
email,
} = resort;
return (
<div className="row mt-5">
<div className="col-lg-7">
<h1>{name}</h1>
<p>
<FaMapMarkerAlt />{" "}
{`${address}, ${city} ${province}, USA, ${zip_code}`}
</p>
<img src={image} alt={name} width="700" />
<br />
<p>{description}</p>
<br />
<h4>Amenities:</h4>
<div>
{resort
? Object.entries(amenities).map(([key, value]) => {
if (value) {
return <p>{key}</p>;
}
return null;
})
: null}
</div>
</div>
</div>
);
};
export default Beach;

React hook page throws 'filter' of undefined (anonymous) exception and unable to perform search

I have implemented a React hookhome page where I have got list of players displaying, I have added an input search to search the players based on the player name or Position, but it throws below exception,could someone please advise the cause of exception;
TypeError: Cannot read property 'filter' of undefined (anonymous
function) C:/Project1/soccerpep/src/components/Home.js:18 15 |
setSearchTerm(event.target.value); 16 | }; 17 | React.useEffect(()
=> {
18 | const results = playerList.name.filter(player =>
| ^ 19 | player.toLowerCase().includes(searchTerm) 20 | ); 21 | setSearchResults(results);
The react hook page follows below:
import React, { useEffect, useState } from "react";
import { Link } from 'react-router-dom';
var playerList = [
{ image: '/images/person.png', name: 'Player 1', position: "Forward" },
{ image: '/images/person.png', name: 'Player 2', position: "Defense" },
{ image: '/images/person.png', name: 'Player 3', position: "Mid Fielder" },
{ image: '/images/person.png', name: 'Player 4', position: "Forward" }
];
const Home = () => {
const [searchTerm, setSearchTerm] = React.useState("");
const [searchResults, setSearchResults] = React.useState([]);
const handleChange = event => {
setSearchTerm(event.target.value);
};
useEffect(() => {
const results = playerList.name.filter(player =>
player.toLowerCase().includes(searchTerm)
);
setSearchResults(results);
}, [searchTerm]);
return (
<div className="App">
<div className="wrapper">
<div className="playerList_header">
<h1>Players</h1>
<label>
<div className="playerSearch_Home">
<div className="playerSearch_Icon">
<img src="/images/search-image-player.jpg"></img>
</div>
<input type="text" className="playerSearch_Home_Input" placeholder="Search players..." value={searchTerm} onChange={handleChange}/>
</div>
</label>
</div>
<div className="playerList_home_page">
<div className="grid-container">
{
playerList.map(player => {
return (
<div className="grid-item">
<div>
<img className="playerProfilePic_home_tile" key={player.image} src={player.image}></img>
</div>
<div className="playerProfile_grid_border">
<h3 key={player.name}>{player.name}</h3>
<span className="playerPosition_home_tile" key={player.position}>{player.position}</span>
</div>
</div>
);
})
},
{
searchResults.map(player => {
return (
<div className="grid-item">
<div>
<img className="playerProfilePic_home_tile" key={player.image} src={player.image}></img>
</div>
<div className="playerProfile_grid_border">
<h3 key={player.name}>{player.name}</h3>
<span className="playerPosition_home_tile" key={player.position}>{player.position}</span>
</div>
</div>
);
})
}
</div>
</div>
</div>
</div>
);
}
export default Home;
playerList is an array, not an object, it doesn't have property name:
const results = playerList.filter(player =>
player.name.toLowerCase().includes(searchTerm) || player.position.toLowerCase().includes(searchTerm)
);
.filter() can be used only on arrays, you tried to run on name property which does not exist.
Instead you can use as the following:
var playerList = [
{ image: '/images/person.png', name: 'Player 1', position: "Forward" },
{ image: '/images/person.png', name: 'Player 2', position: "Defense" },
{ image: '/images/person.png', name: 'Player 3', position: "Mid Fielder" },
{ image: '/images/person.png', name: 'Player 4', position: "Forward" }
];
const searchTerm = 'Player 2';
const results = playerList.filter(p => p.name.toLowerCase() === searchTerm.toLowerCase());
console.log(results);
I hope this explains!

Categories