Display an array of objects on a page - javascript

I'm trying to render objects that are in an array into my DOM.
I'm trying to display each object in its own card for viewing (using Tailwind css).
I'm fairly new to coding so I feel like it's something very simple that I'm overlooking here. Any help would be greatly aprpeciated!
const productsDOM = document.querySelector(`.products`);
const itemObject = [{
title: "Chocolate",
price: 10.99,
id: 1,
img: "https://images.pexels.com/photos/1055272/pexels-photo-1055272.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260"
}, {
title: "Whipped Cream",
price: 12.99,
id: 2,
img: "https://images.pexels.com/photos/1055270/pexels-photo-1055270.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260"
}, {
title: "White Frosting",
price: 12.99,
id: 3,
img: "https://images.pexels.com/photos/1055271/pexels-photo-1055271.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260"
}, {
title: "Berry",
price: 14.99,
id: 4,
img: "https://images.pexels.com/photos/3081657/pexels-photo-3081657.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260"
}, {
title: "Deluxe",
price: 19.99,
id: 5,
img: "https://images.pexels.com/photos/1998634/pexels-photo-1998634.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260"
}, {
title: "Oreo",
price: 14.99,
id: 6,
img: "https://images.pexels.com/photos/783274/pexels-photo-783274.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260"
}];
function displayProducts() {
let html = ``;
itemObject.forEach(() => {
html += `
<div id="item-1" class="bg-white rounded-lg">
<img class="rounded-md w-screen object-cover max-h-60"
src="${itemObject.img}"
alt="">
<div class="py-2 px-8 text-gray-600">
<div class="grid grid-cols-2 py-3 text-xl font-bold ">
<h3>${itemObject.title}</h3>
<p class="text-right">$${itemObject.price}</p>
</div>
<button data-id=${itemObject.id}
class="bg-purple-200 font-bold px-3 mt-2 text-xl py-4 w-full rounded-md transition-all hover:bg-purple-300">Purchase</button>
</div>
</div>
`;
});
productsDOM.innerHTML = html;
}

You can use for loop, or even forEach() create Element, it doesn't matter it will be div, span, h1 or what and use innerText to declare your object names as text, and call your DOM Element before you use for loop and append them as child in your Element via .appendChild
In that case I used template strings it is easier to use, when you have to append lot of data from object
For Loop
const container = document.querySelector(".container")
const data = [
{name: "george", age: 12},
{name: "Maria", age: 35},
{name: "Lucas", age: 65}
]
for(let i = 0; i < data.length; i++){
const usersBox = document.createElement("div")
usersBox.className = "usersBox"
const list = document.createElement("p")
list.innerText = `${data[i].name}: ${data[i].age}`
usersBox.appendChild(list)
container.appendChild(usersBox)
}
.usersBox{
display: flex;
border: 2px solid black
}
<div class="container">
</div>
.forEach()
const container = document.querySelector(".container")
const data = [
{name: "george", age: 12},
{name: "Maria", age: 35},
{name: "Lucas", age: 65}
]
data.forEach(users => {
const usersBox = document.createElement("div")
usersBox.className = "usersBox"
const list = document.createElement("p")
list.innerText = `${users.name}: ${users.age}`
usersBox.appendChild(list)
container.appendChild(usersBox)
})
.usersBox{
display: flex;
border: 2px solid black;
}
<div class="container">
</div>

You forgot to "capture" each element in your array inside forEach function:
itemObject.forEach((item) => {
Once that's done, you can use item instead of itemObject inside your template. Also ID must be unique, so you can capture index of current item in the array as well and use it in your template:
itemObject.forEach((item, index) => {
const productsDOM = document.querySelector(`.products`);
const itemObject = [{
title: "Chocolate",
price: 10.99,
id: 1,
img: "https://images.pexels.com/photos/1055272/pexels-photo-1055272.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260"
}, {
title: "Whipped Cream",
price: 12.99,
id: 2,
img: "https://images.pexels.com/photos/1055270/pexels-photo-1055270.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260"
}, {
title: "White Frosting",
price: 12.99,
id: 3,
img: "https://images.pexels.com/photos/1055271/pexels-photo-1055271.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260"
}, {
title: "Berry",
price: 14.99,
id: 4,
img: "https://images.pexels.com/photos/3081657/pexels-photo-3081657.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260"
}, {
title: "Deluxe",
price: 19.99,
id: 5,
img: "https://images.pexels.com/photos/1998634/pexels-photo-1998634.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260"
}, {
title: "Oreo",
price: 14.99,
id: 6,
img: "https://images.pexels.com/photos/783274/pexels-photo-783274.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260"
}];
function displayProducts() {
let html = ``;
itemObject.forEach((item,index) => {
html += `
<div id="item-${index}" class="bg-white rounded-lg">
<img class="rounded-md w-screen object-cover max-h-60"
src="${item.img}"
alt="">
<div class="py-2 px-8 text-gray-600">
<div class="grid grid-cols-2 py-3 text-xl font-bold ">
<h3>${item.title}</h3>
<p class="text-right">$${item.price}</p>
</div>
<button data-id=${item.id}
class="bg-purple-200 font-bold px-3 mt-2 text-xl py-4 w-full rounded-md transition-all hover:bg-purple-300">Purchase</button>
</div>
</div>
`;
});
productsDOM.innerHTML = html;
}
displayProducts();
<div class="products"></div>

you have problem in your forEach loop, try this :
function displayProducts() {
let html = ``;
itemObject.forEach((el) => {
html += `
<div id="item-1" class="bg-white rounded-lg">
<img class="rounded-md w-screen object-cover max-h-60"
src="${el.img}"
alt="">
<div class="py-2 px-8 text-gray-600">
<div class="grid grid-cols-2 py-3 text-xl font-bold ">
<h3>${el.title}</h3>
<p class="text-right">$${el.price}</p>
</div>
<button data-id=${itemObject.id}
class="bg-purple-200 font-bold px-3 mt-2 text-xl py-4 w-full rounded-md transition-all hover:bg-purple-300">Purchase</button>
</div>
</div>
`;
});
productsDOM.innerHTML = html;
}

Related

How to add onhover to Combobox from headlessui

This is the component that must be used.
Here is its source code:
import { Fragment, useState } from 'react'
import { Combobox, Transition } from '#headlessui/react'
import { CheckIcon, SelectorIcon } from '#heroicons/react/solid'
const people = [
{ id: 1, name: 'Wade Cooper' },
{ id: 2, name: 'Arlene Mccoy' },
{ id: 3, name: 'Devon Webb' },
{ id: 4, name: 'Tom Cook' },
{ id: 5, name: 'Tanya Fox' },
{ id: 6, name: 'Hellen Schmidt' },
]
export default function Example() {
const [selected, setSelected] = useState(people[0])
const [query, setQuery] = useState('')
const filteredPeople =
query === ''
? people
: people.filter((person) =>
person.name
.toLowerCase()
.replace(/\s+/g, '')
.includes(query.toLowerCase().replace(/\s+/g, ''))
)
return (
<div className="fixed top-16 w-72">
<Combobox value={selected} onChange={setSelected}>
<div className="relative mt-1">
<div className="relative w-full cursor-default overflow-hidden rounded-lg bg-white text-left shadow-md focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 focus-visible:ring-offset-2 focus-visible:ring-offset-teal-300 sm:text-sm">
<Combobox.Input
className="w-full border-none py-2 pl-3 pr-10 text-sm leading-5 text-gray-900 focus:ring-0"
displayValue={(person) => person.name}
onChange={(event) => setQuery(event.target.value)}
/>
<Combobox.Button className="absolute inset-y-0 right-0 flex items-center pr-2">
<SelectorIcon
className="h-5 w-5 text-gray-400"
aria-hidden="true"
/>
</Combobox.Button>
</div>
<Transition
as={Fragment}
leave="transition ease-in duration-100"
leaveFrom="opacity-100"
leaveTo="opacity-0"
afterLeave={() => setQuery('')}
>
<Combobox.Options className="absolute mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
{filteredPeople.length === 0 && query !== '' ? (
<div className="relative cursor-default select-none py-2 px-4 text-gray-700">
Nothing found.
</div>
) : (
filteredPeople.map((person) => (
<Combobox.Option
key={person.id}
className={({ active }) =>
`relative cursor-default select-none py-2 pl-10 pr-4 ${
active ? 'bg-teal-600 text-white' : 'text-gray-900'
}`
}
value={person}
>
{({ selected, active }) => (
<>
<span
className={`block truncate ${
selected ? 'font-medium' : 'font-normal'
}`}
>
{person.name}
</span>
{selected ? (
<span
className={`absolute inset-y-0 left-0 flex items-center pl-3 ${
active ? 'text-white' : 'text-teal-600'
}`}
>
<CheckIcon className="h-5 w-5" aria-hidden="true" />
</span>
) : null}
</>
)}
</Combobox.Option>
))
)}
</Combobox.Options>
</Transition>
</div>
</Combobox>
</div>
)
}
My question is: is it possible to show some information for an element when we hover over it?
For example, if we modify the input to this one:
const people = [
{ id: 1, name: 'Wade Cooper', info: 'test1' },
{ id: 2, name: 'Arlene Mccoy', info: 'test2' },
{ id: 3, name: 'Devon Webb', info: 'test3' },
{ id: 4, name: 'Tom Cook', info: 'test4' },
{ id: 5, name: 'Tanya Fox', info: 'test5' },
{ id: 6, name: 'Hellen Schmidt', info: 'test6' },
]
When we hover over first element, to show test1, for the second element test2 and so on.
I am not a react expert(/user). But for the Combobox component is 'active' the key word for hover. You have to conditionally render your displayed text/or the whole span like in pseudocode(however you conditionally render stuff in react):
active ? person.info : person.name

How to enable/add anchor tag to the string in ReactJS?

The follwing is the code I've written and when I rendered it, item.about which has <a> tag, cannot render it and [object Object] is being displayed instead of that JSX. JSON.stringify does not even render it.
export default function Team() {
const teamList = [
{
id: 1,
name: "User",
image: user,
designation: "User",
about:
"He created Zoom Church LK </a>}. Apart from shipping apps, He Writes/Produces/Performs Music.",
},
{
id: 2,
name: "User 2",
image: user,
designation: "User",
about:
`He created ${ Zoom Church LK }. Apart from shipping apps, He Writes/Produces/Performs Music.`,
},
];
return (
<section className="leading-relaxed max-w-screen-xl mt-12 mx-auto px-4 lg:px-8 mb-20">
<div className="space-y-3 text-center">
<h1 className="text-5xl text-gray-400 font-black">Meet Our Team</h1>
<p className="text-gray-500 max-w-lg mx-auto text-lg">
Focused. Improving. Data-driven.
</p>
</div>
<div className="mt-14 gap-4 sm:grid sm:grid-cols-2 lg:grid-cols-3">
{teamList.map((item) => (
<div className="space-y-3 mt-5" key={item.id}>
<div className="object-center lg:w-full rounded-lg card-zoom">
<img
src={item.image}
alt={item.name}
/>
</div>
<h4 className="text-xl text-gray-400 font-bold">{item.name}</h4>
<h5 className="text-lg text-gray-400 font-medium">
{item.designation}
</h5>
<p className="text-gray-500">{(JSON.stringify(item.about))}</p>
</div>
))}
</div>
</section>
);
}
What would be the best way to modify my component to be able to add links like this?
To render links change your teamList like this:-
const teamList = [
{
id: 1,
name: "User",
image: user,
designation: "User",
about: <>He created Zoom Church LK . Apart from shipping apps, He Writes/Produces/Performs Music.</>,
},
{
id: 2,
name: "User 2",
image: user,
designation: "User",
about: <>He created Zoom Church LK . Apart from shipping apps, He Writes/Produces/Performs Music.</>,
},
];
and then render it like this
<p className="text-gray-500">{item.about}</p>
// you have to use tags without ${} when
// you want to use them in strings
const teamList = [
{
id: 1,
name: "User",
image: user,
designation: "User",
about:
"He created <a href='https://hanancs.github.io/ZoomChurchLK'> Zoom Church LK </a>. Apart from shipping apps, He Writes/Produces/Performs Music.",
},
{
id: 2,
name: "User 2",
image: user,
designation: "User",
about:
`He created <a href='https://hanancs.github.io/ZoomChurchLK'> Zoom Church LK </a>. Apart from shipping apps, He Writes/Produces/Performs Music.`,
},
];
// you can use dangerouslySetInnerHTML to show
//html tag inside of strings.
return (
{teamList.map((team) => (
<div dangerouslySetInnerHTML={{ __html: team.about }} key={team.id} />
))}
)

React Hooks add/subtract count from click div/list

The problem is that the count needs to be subtracted from the total when the item on the list has been un-selected. So far it works when the item is selected and the count goes up. Maybe some kind of toggle is needed to subtract the total from the count. And if the count is zero it needs to show and empty div with no zero or numbers. thanks in advance if anyone can help out 😀🐍🏴‍☠️
Sandbox here : https://codesandbox.io/s/checkbox-counter-friday-28-fgp85?file=/src/App.js:0-948
export const DropdownMenu = (props) => {
const [selectedMenu, setSelectedMenu] = useState([]);
return (
<div className="flex justify-center relative -mr-10">
<div className="absolute top-10 w-240 opacity-100 bg-white -ml-48 shadow-md rounded-lg text-left p-3 z-30">
<span className="text-center inline-block w-3">
{selectedMenu.length}
</span>
{props.options &&
props.options.map((option, _idx) => (
<div key={option.id} className={props.titleAndSubtitleGroup}>
<div className="flex flex-row">
<input
onClick={() => {
!selectedMenu.includes(option) &&
setSelectedMenu((oldValue) => [...oldValue, option]);
}}
type="checkbox"
id={option.group}
className="bg-white border-2 rounded w-4 h-4 mt-1 flex flex-shrink-0 justify-center items-center mr-2 focus-within:border-blue-0"
/>
<label
htmlFor={option.groupId}
className={"no-underline hover:underline"}
>
{option.text}{" "}
</label>
</div>
</div>
))}
</div>
</div>
);
};
export default DropdownMenu;
import React from "react";
import DropdownMenu from "./DropdownMenu";
export const App = () => {
return (
<DropdownMenu
options={[
{
id: 1,
text: "Post",
icon: "",
url: "/#",
group: "01",
groupId: "01"
},
{
id: 2,
text: "Delete",
icon: "",
url: "/#",
group: "02",
groupId: "02"
},
{
id: 3,
text: "Forward",
icon: "",
url: "/#",
group: "03",
groupId: "03"
},
{
id: 4,
text: "Share",
icon: "",
url: "/#",
group: "04",
groupId: "04"
},
{
id: 5,
text: "Copy Link",
icon: "",
url: "/#",
group: "05",
groupId: "05"
}
]}
/>
);
};
export default App;```
You aren't removing elements from the selectedMenu array when the checkbox is unchecked.
I suggest using an object instead of an array to store a map of option id to checked status. Then get an array of values from the selectedMenu state and filter by what is selected to get a derived selected count.
const [selectedMenu, setSelectedMenu] = useState({});
...
<span className="text-center inline-block w-3">
{Object.values(selectedMenu).filter(Boolean).length}
</span>
or to conditionally only display non-zero values (this OFC can be optimized to be more DRY)
<span className="text-center inline-block w-3">
{!!Object.values(selectedMenu).filter(Boolean).length &&
Object.values(selectedMenu).filter(Boolean).length}
</span>
...
<input
onChange={e => {
const { id, checked } = e.target;
setSelectedMenu(selected => ({
...selected,
[id]: checked
}))
}}
type="checkbox"
id={option.group}
className="bg-white border-2 rounded w-4 h-4 mt-1 flex flex-shrink-0 justify-center items-center mr-2 focus-within:border-blue-0"
/>
OFC, if you wanted, or needed, to keep the array, then just conditionally filter the array, or append a value.
<input
onClick={() => {
selectedMenu.includes(option.id)
? setSelectedMenu((oldValue) =>
oldValue.filter((val) => val !== option.id)
)
: setSelectedMenu((oldValue) => [...oldValue, option.id]);
}}
type="checkbox"
id={option.group}
className="bg-white border-2 rounded w-4 h-4 mt-1 flex flex-shrink-0 justify-center items-center mr-2 focus-within:border-blue-0"
/>

Vue - Disable button when item is added to cart. Enable when it's removed

I'm trying to add functionality to my addToCart button located in ProductCard. I need it to be disabled once the cupcake has been added to my cart array. When removed via the removeItem/ clearCart in MiniCart I need the button to be enabled again. I've tried if else statements and tried adding all kinds of functionality that I've Google's but have yet to succeed. I'd really appreciate some help ^^
store.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export const store = new Vuex.Store({
state: {
cart: [],
cupcake: [{
title: 'Cream',
price: 12.99,
image: 'https://images.pexels.com/photos/1055270/pexels-photo-1055270.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260',
id: 1,
quantity: 1
},
{
title: 'Choc',
price: 10.99,
image: 'https://images.pexels.com/photos/1055272/pexels-photo-1055272.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260',
id: 2,
quantity: 1
},
{
title: 'Frosting',
price: 14.99,
image: 'https://images.pexels.com/photos/1055271/pexels-photo-1055271.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260',
id: 3,
quantity: 1
},
{
title: 'Berry',
price: 9.99,
image: 'https://images.pexels.com/photos/3081657/pexels-photo-3081657.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260',
id: 4,
quantity: 1
},
{
title: 'Deluxe',
price: 19.99,
image: 'https://images.pexels.com/photos/1998634/pexels-photo-1998634.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260',
id: 5,
quantity: 1
},
{
title: 'Oreo',
price: 19.99,
image: 'https://images.pexels.com/photos/783274/pexels-photo-783274.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260',
id: 6,
quantity: 1
},
]
},
});
ProductCard.vue
<template>
<ul
class="
px-32
py-16
grid
row-auto
gap-10
grid-cols-1
md:grid-cols-2
xl:grid-cols-3
2xl:grid-cols-4
"
>
<li
class="bg-white rounded-lg"
v-for="cupcakes in cupcake"
:key="cupcakes.id"
>
<img
class="rounded-md w-screen object-cover max-h-60"
:src="cupcakes.image"
/>
<div class="py-2 px-8 text-gray-600">
<span class="px-10 text-xl font-bold"> {{ cupcakes.title }}</span>
<span class="px-10 text-xl font-bold">${{ cupcakes.price }}</span>
<button
class="
bg-purple-200
font-bold
px-3
mt-2
text-xl
py-4
mb-4
w-full
rounded-md
transition-all
hover:bg-purple-300
"
type="button"
v-on:click="addToCart(cupcakes)"
>
Add to Cart
</button>
</div>
</li>
</ul>
</template>
<script>
export default {
computed: {
cupcake() {
return this.$store.state.cupcake;
},
},
methods: {
addToCart(cupcakes) {
this.$store.state.cart.push({
title: cupcakes.title,
price: cupcakes.price,
image: cupcakes.image,
id: cupcakes.id,
quantity: cupcakes.quantity,
});
},
},
};
</script>
Minicart.vue
<template>
<div class="bg-white border-2 border-gray-500 rounded-md absolute right-16">
<div
class="grid grid-cols-2 gap-20 m-5"
v-for="carts in cart"
:key="carts.id"
>
<img class="w-24" :src="carts.image" alt="" />
<div class="grid grid-rows-3">
<strong class="tracking-wider font-bold">{{ carts.title }}</strong>
<p class="tracking-wider font-bold">
{{ carts.quantity }} x ${{ carts.price }}
</p>
<button
class="bg-gray-500 rounded p-2 tracking-wider font-bold text-white"
v-on:click="removeItem(carts)"
>
remove
</button>
<button type="button" v-on:click="increase(carts)">Increase</button>
<button type="button" v-on:click="deccrease(carts)">Deccrease</button>
</div>
</div>
<div class="flex mx-5 my-8 justify-between">
<span
class="tracking-wider text-xl p-4 font-bold justify-center align-middle"
>Total: ${{ total }}</span
>
<button
v-on:click="clearCart"
type="button"
href=""
class="
bg-red-400
p-4
rounded
tracking-wider
text-white text-xl
font-bold
"
>
Clear Cart
</button>
</div>
</div>
</template>
<script>
export default {
computed: {
cart() {
return this.$store.state.cart;
},
total: function () {
let total = 0;
for (let carts of this.$store.state.cart) {
total += carts.price * carts.quantity;
}
return total.toFixed(2);
},
},
methods: {
removeItem: function (carts) {
this.$store.state.cart.splice(carts, 1);
},
increase: function (carts) {
carts.quantity += 1;
},
deccrease: function (carts) {
if (carts.quantity > 1) {
carts.quantity -= 1;
} else {
this.$store.state.cart.splice(carts, 1);
}
},
clearCart: function () {
let length = this.$store.state.cart.length;
this.$store.state.cart.splice(0, length);
console.log(length);
},
},
};
</script>
Just like that. Demo https://codesandbox.io/s/jolly-shirley-dgg10
Template:
<button
class="bg-purple-200 font-bold px-3 mt-2 text-xl py-4 mb-4 w-full
rounded-md transition-all hover:bg-purple-300"
type="button"
v-on:click="addToCart(cupcakes)"
:disabled="checkCart(cupcakes.id)"
>
Add to Cart
</button>
Methods:
checkCart(id) {
return this.$store.state.cart.find((item) => item.id === id);
},
If you add this disabled-method to your button, it will be disabled, if the cupcake is already in the cart, and you can still add the other cupcakes:
<button
class="
...
"
type="button"
v-on:click="addToCart(cupcakes)"
:disabled="{ cart.includes(cupcakes) }"
>
Add to Cart
</button>
Your AddToCart-function could also be rewritten to:
addToCart(cupcakes) {
this.$store.state.cart.push(cupcakes);
},

Show Less/Show More button using react hook?

This is my data, initially I want show only 4 albums on the page, then when a user click on Show More I want to load the next 4 albums. And when user click on the Show Less button, it goes back to the previous/initial state.
cardData: [
{
id: 1,
img: eight0eightheartbreak,
title: '808 & Heartbreak',
desc: 'desc 1'
},
{
id: 2,
img: collegedropout,
title: 'College Dropout',
desc: 'desc 2'
},
{
id: 3,
img: graduation,
title: 'Graduation',
desc: 'desc 3'
},
{
id: 4,
img: lateregistration,
title: 'Late Registration',
desc: 'desc 4'
},
{
id: 5,
img: MBDTF,
title: 'My Beatiful Dark Twisted Fantesy',
desc: 'desc 5'
},
{
id: 6,
img: TLOP,
title: 'The Life of Pablo',
desc: 'desc 6'
},
{
id: 7,
img: Ye,
title: 'Ye',
desc: 'desc 7'
},
{
id: 8,
img: yeezus,
title: 'Yeezus',
desc: 'desc 8'
},
{
id: 9,
img: JIK,
title: 'Jesus Is King',
desc: 'desc 9'
}
]
}
this is my code
const [readMore, setReadMore] = useState(false);
const [noOfElements, setnoOfElements] = useState(4);
const slice = Data.cardData.slice(0, noOfElements);
const loadMore = ()=>{
setnoOfElements(noOfElements + 4)
}
return (
<section className="py-4 container">
<div className="row justify-content-center">
{slice.map((item, index)=>{
return(
<div className= "col-11 col-md-6 col-lg-3 max-0 mb-4">
<div className="card p-0 overflow-hidden h-100 shadow">
<img src={item.img} alt="" className="card-img-top" />
<div className="card-body">
<h5 className="card-title">{item.title}</h5>
<p className="card-text">{item.desc}</p>
</div>
</div>
</div>
)
})}
</div>
<button className="btn btn-dark d-block-w-100" onClick={()=>loadMore()} >
Read more
</button>
</section>
)
}
I have managed to create a Show more button, now how do I create Show Less button using the same logic, react useState hook? I know how to make it using component, but I want to do it using useState, is there anyway I can do it?
You can just put a conditional tag in your slice.map:
{slice.map((item, index)=>{
if( index <= noOfElements ){
return <div className= "col-11 col-md-6 col-lg-3 max-0 mb-4">...</div>
}
}
const [readMore, setReadMore] = useState(false);
const [noOfElements, setnoOfElements] = useState(4);
const slice = Data.cardData.slice(0, noOfElements);
const loadMore = ()=>{
setnoOfElements(noOfElements + 4)
}
const loadLess = ()=>{
setnoOfElements(noOfElements - 4)
}
return (
<section className="py-4 container">
<div className="row justify-content-center">
{slice.map((item, index)=>{
return(
<div className= "col-11 col-md-6 col-lg-3 max-0 mb-4">
<div className="card p-0 overflow-hidden h-100 shadow">
<img src={item.img} alt="" className="card-img-top" />
<div className="card-body">
<h5 className="card-title">{item.title}</h5>
<p className="card-text">{item.desc}</p>
</div>
</div>
</div>
)
})}
</div>
<button className="btn btn-dark d-block-w-100" onClick={()=>loadMore()} >
Read more
</button>
<button className="btn btn-dark d-block-w-100" onClick={()=>loadLess()} >
Read less
</button>
</section>
)
Is this is you actually needed?

Categories

Resources