简体   繁体   中英

React JS: Check if each item on object is true and then add icons

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM