So I have this test dummy data here:
{
_id: "1",
name: "Lakawon Island Resort",
price_per_night: 2804.0,
description:
"On a lush 16-hectare island with white-sand beaches, this relaxed resort is 5 km from the jetty in Cadiz Viejo, a village on the mainland.",
address: "Cadiz Viejo",
city: "New York",
state: "New York",
zip_code: "6121",
latitude: 11.045411,
longitude: 123.201465,
phone: "(034) 213 6354",
email: "info@example.com",
website: 'www.lakawonislandresort.us',
amenities:
{
tv: false,
reservation: false,
cabin: true,
services: true,
},
image:
"https://images.unsplash.com/photo-1512356181113-853a150f1aa7",
rating: 4.5,
reviews: 11,
},
Notice that I have this object amenities
which is also an object. Currently I have 4 sub object there tv
, reservation
, cabin
and services
.
What I need is to check each item if they are true, if they are indeed true then return the key of the object and add a font-awesome icon right beside it. Otherwise if the value is false do nothing or return null.
So far here's how I implemented it:
{
amenities && Object.entries(amenities).map(
([key, value]) => {
if(key === 'tv' && key[value] === true){
return `<p><i class="fa fa-tv"></i> ${key}</p>`
} else if (key === 'reservation' && key[value] === true){
return `<p><i class="fa fa-reservation"></i> ${key}</p>`
}else if (key === 'cabin' && key[value] === true){
return `<p><i class="fa fa-cabin"></i> ${key}</p>`
}else if (key === 'services' && key[value] === true){
return `<p><i class="fa fa-service"></i> ${key}</p>`
}
return null
}
)
}
However this did not work, instead its returning a Can't map through object
error.
Any idea how can I check each key if they are true and then output their respective fontawesome icon beside it if the value is true? Is there a more efficient way to do this than if else statement?
Here's the complete code for that component:
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}, Philippines, ${zip_code}`}</p>
<img src={image} alt={name} width="700" />
<br/>
<p>{description}</p>
<br/>
<h4>Amenities:</h4>
<div>
{
amenities && Object.entries(amenities).map(
([key, value]) => {
if(key === 'tv' && key[value] === true){
return `<p><i class="fa fa-tv"></i> ${key}</p>`
} else if (key === 'reservation' && key[value] === true){
return `<p><i class="fa fa-reservation"></i> ${key}</p>`
}else if (key === 'cabin' && key[value] === true){
return `<p><i class="fa fa-cabin"></i> ${key}</p>`
}else if (key === 'services' && key[value] === true){
return `<p><i class="fa fa-service"></i> ${key}</p>`
}
return null
}
)
}
</div>
</div>
</div>
)
}
export default Beach
You can do something more shorthand
{amenities &&
Object.keys(amenities)
.filter((key) => amenities[key])
.map((key) => {
if (key === "tv") {
return (
<p>
<i class="fa fa-tv"></i> {key}
</p>
);
} else if (key === "reservation") {
return (
<p>
<i class="fa fa-reservation"></i> {key}
</p>
);
} else if (key === "cabin") {
return (
<p>
<i class="fa fa-cabin"></i> {key}
</p>
);
} else if (key === "services") {
return (
<p>
<i class="fa fa-service"></i> {key}
</p>
);
}
})}
Check out the current codesandbox i've made : https://codesandbox.io/s/optimistic-darkness-yt9sy?file=/src/Beach.js
Why and How:
Basically, if you only need to test if your key === 'something' and check if the value is true or false, you could do this way:
First your filter the object so it keep only truthy values. Then on your .map() you'll know you get truthy keys so you just handle de conditionnal rendering based on the key value
.filter((key) => amenities[key]) // will filter out every values not truthy
myCurrentKey: '' // would be filtered out
myCurrentKey: 1 // would not be filtered out
Also, for my point of view when you have Object that you want to render, try to go first with Object.keys().map(), that's the easy way and more readable way to do, unless you need something really custom, you could do with the Object.entries, or else.
It can be done that way:
const { amenities = {} } = resort;
return (
<div>
{Object.keys(amenities).map(item => {
return amenities[item] ? <p><i class={`fa fa-${item}`}></i>{item}</p> : null;
})}
</div>
)
But I think the mapping isn't really needed here and you can just keep it simple:
const { amenities = {} } = resort;
return (
<div>
{amenities.tv && <p><i class="fa fa-tv"></i>tv</p>}
{amenities.reservation && <p><i class="fa fa-reservation"></i>reservation</p>}
{amenities.cabin && <p><i class="fa fa-cabin"></i>cabin</p>}
{amenities.services && <p><i class="fa fa-service"></i>services</p>}
</div>
)
Try this:
amenities && Object.entries(amenities).filter(([key,value]) => value === true).map(
([key]) => {
switch(key){
case 'tv':
return <p><i class="fa fa-tv"></i> {key}</p>;
case 'reservation':
return <p><i class="fa fa-reservation"></i> {key}</p>;
case 'cabin':
return <p><i class="fa fa-cabin"></i> {key}</p>;
case 'services':
return <p><i class="fa fa-services"></i> {key}</p>;
default:
return null;
}
})
I think your problem is that you use key[value]
when key
is a string and value
is a boolean
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.