How do I show multiple items using bootstrap carousel - javascript

I am trying to use carousel in my react project to show reviews. I am using bootstrap carousel.
This is the carousel I am using
But I want to use like this
Every click on the button will slide in a item and one item will slide out.
I can do one at a time but not like this.
Here is my Code:
const ShowReviews = () => {
const { data: reviews, isLoading, refetch } = useQuery('reviews', () => fetch('https://.herokuapp.com/reviews',)
.then(res => res.json()))
refetch()
if (isLoading) {
return <Loading></Loading>
}
return (
<div>
<h1 className='text-center fw-bold my-5'>User Reviews ({reviews.length})</h1>
<div className='bg-dark bg-opacity-25 container-fluid'>
<Carousel>
{reviews.map(review => <Carousel.Item> <ReviewCard
key={review._id}
review={review}
></ReviewCard></Carousel.Item>)}
</Carousel>
</div>
</div>
);
};
export default ShowReviews;

Just put three review cards per Carousel.Item instead of one. Carousel.Item is just a wrapper for one carousel "page".
Carousel.Item is already styled in a certain way, that's why you need a container/wrapper right below it. In my example I used Stack with direction="horizontal":
<Carousel.Item style={{ height: 500 }}>
<Stack
direction="horizontal"
className="h-100 justify-content-center align-items-center"
gap={3}
>
<Card>...</Card>
<Card>...</Card>
<Card>...</Card>
</Stack>
</Carousel.Item>
https://codesandbox.io/s/relaxed-poitras-4w774i

Related

React: How to display a modal without encountering error message (details provided)

Intro
When my application starts, a list of images appear. If additional details about an image is required, a user can click on an image that has previously loaded, and a modal would appear with it's relevant details.
Even though everything works as it should, I'm encountering an error message that can be found in Chrome browser's console.
Error
Warning: Each child in a list should have a unique "key" prop.
Attempted
I've tried placing key={Math.floor(Date.now() * 20)} within the Image found in the modal, but that doesn't work.
Where am I going wrong? How can I fix this issue?
function getHomePage() {
const [token, setToken] = useState("");
const [visibility, setVisibility] = useState(false);
const [NFTBalances, setNFTBalances] = useState();
const [collection, setCollection] = useState();
const [nft, setNft] = useState();
const { Moralis } = useMoralis();
//load my images when application starts
useEffect(() => {
collectionChanged('myCollection');
}, []);
const handleSelectToken = async (num, col) => {
if (num && col) {
const dbNFTs = Moralis.Object.extend(col);
const query = new Moralis.Query(dbNFTs);
console.log(num);
query.equalTo("tokenId", num);
let selectedNFT = await query.first();
selectedNFT = selectedNFT.attributes;
console.log(selectedNFT);
setNft(selectedNFT);
setVisibility(true);
//open modal
$("#openModal").modal("show");
}
};
const addToNFTs = async (col) => {
const dbNFTs = Moralis.Object.extend(col);
const query = new Moralis.Query(dbNFTs);
query.ascending("rank");
query.limit(4);
const topNFTs = query.skip(NFTBalances.length);
const results = await topNFTs.find();
setNFTBalances(NFTBalances.concat(results));
}
return (
<>
//modal box
<div className="modal fade" id="openModal" tabIndex="-1" role="dialog" aria-hidden="true">
<div className="modal-dialog modal-lg" role="document">
<div className="modal-content">
<div className="modal-header">
<button type="button" className="close"
data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div className="modal-body">
<div>
<Image key={Math.floor(Date.now() * 20)}
preview={false} src={nft.image} loading="lazy"
style={{ display: "block", width: "50%"}}/>
<p>{nft.details}</p>
</div>
</div>
</div>
</div>
</div>
<div className="col-xxl-3 col-xl-3 col-lg-3 col-md-3">
<div className="filter-sidebar">
<div className="filter-sidebar-content">
<div className="form-group">
//SEARCH BOX
<Search placeholder="Please search here"
onChange={(e) => setToken(e.target.value) }
onSearch={() => handleSelectToken(token, collection)} />
</div>
</div>
</div>
</div>
//Images populate when application loads
//Clicking an image will populate image details in a modal
<div className="row">
{NFTBalances && NFTBalances.map((nft, index) => {
return (
<div className="col-xxl-3 col-xl-3 col-lg-6 col-md-6">
<div className="card items">
<Card key={index} onClick={() =>
handleSelectToken(nft.attributes.tokenId,collection)}
cover={ <Image src={nft.attributes.image} /> }>
</Card>
</div>
</div>
);})}
</div>
</>
);}
export default getHomePage;
You're placing the key at the wrong place. You're not rendering a list of images, but rather a list of cards containing images, here is where you need to add the key prop. You've already added a key to the card itself, butit needs to be present on the parent element. You can use index only if you do not expect the order of these to change during render. Alternatively use your key={Math.floor(Date.now() * 20)}.
{NFTBalances && NFTBalances.map((nft, index) => {
return (
<div key={index} className="col-xxl-3 col-xl-3 col-lg-6 col-md-6">
<div className="card items">
<Card onClick={() =>
handleSelectToken(nft.attributes.tokenId,collection)}
cover={ <Image src={nft.attributes.image} /> }>
</Card>
</div>
</div>
);})}
</div>
</>
);}
In modal box the key for the <Image> is causing an issue since the key values need to be unique.
By setting key={Math.floor(Date.now() * 20)}, every <Image> will end up with the same key since they are rendered at the same time.
You should be able to just remove key from that line:
<Image preview={false} src={nft.image} loading="lazy" style={{ display: "block", width: "50%"}}/>
But if that ends up giving you issues, you could also generate a key randomly:
<Image key={Math.random().toString()} preview={false} src={nft.image} loading="lazy" style={{ display: "block", width: "50%"}}/>
I don't know what your nft object looks like, but if each one has its own unique id, that id would be ideal to use for key. This answer explains why that is.
<Image key={nft.id} preview={false} src={nft.image} loading="lazy" style={{ display: "block", width: "50%"}}/>
Another issue is that there is no key being set on the immediate child inside of .map. You should be setting the key on the div that comes right after return:
{NFTBalances && NFTBalances.map((nft, index) => {
return (
<div key={index} className="col-xxl-3 col-xl-3 col-lg-6 col-md-6">
<div className="card items">
<Card onClick={() =>
handleSelectToken(nft.attributes.tokenId,collection)}
cover={ <Image src={nft.attributes.image} /> }>
</Card>
</div>
</div>
Good luck! They key prop is pretty important in React. Here's a bit more information from a great answer about key if you want to learn more.
{NFTBalances && NFTBalances.map((nft, index) => {
return (
<div className="col-xxl-3 col-xl-3 col-lg-6 col-md-6">
Keys are needed when you make an array of elements, and so this <div> is where you need to put the key. Ideally, it will be some unique identifier found in the nft object. Since i don't know the structure of your data i can't be sure the best value to use, but assuming nft.attributes.tokenId is unique and always present:
<div key={nft.attributes.tokenId} className="col-xxl-3 col-xl-3 col-lg-6 col-md-6">
If there is no unique identifier on nft, then as a last resort you could use the index, but this will only work correctly if you are not rearranging this list.
<div key={index} className="col-xxl-3 col-xl-3 col-lg-6 col-md-6">
key={Math.floor(Date.now() * 20)}
This is a bad key. First, it's not going to be unique: all these <div>s are being created at basically the same time, so in all likelyhood they'll all get the same value for Date.now(). Second, they are going to change from one render to the next.
The point of keys in react is to tell react which element in the first render corresponds to which element in the second render. If they're all changing, then react thinks it needs to throw out everything and start again (ie, it must unmount and remount all the components)

How to get the properties when a slide is clicked in swiperjs without jquery

I am trying to get the values of a specific card when it is clicked in swiperJS but am not finding in the documentation if it is possible to do so.
Hoping to not resort to wrapping each slide in a label and input button.
My code here:
<Swiper
slidesPerView={'auto'}
spaceBetween={200}
centeredSlides={true}
pagination={{
"clickable": true
}}>
{Cards.map((card, idx) => {
return (
<div className="row" style={{ display: 'inline-block' }}>
<div className="col-12 swiper-container">
<SwiperSlide>
<Cards
number={card.number}
name={card.name}
expiry={card.expiry}
cvc={card.cvc}
// focused={focus}
/>
</SwiperSlide>
</div>
</div>
)
})}
</Swiper>
Is it possible to do so?
Looking at swiper's react source code it seems like SwiperSlide renders by default into a div node . This node can receive a onClick prop, which should execute whatever function you want. That would look something like this:
<SwiperSlide onClick={()=> console.log(card.name)}>
// ...
</SwiperSlide>
If for some reason that doesn't work either, consider adding the onClick to a div already wrapping the slide (for example div.col-12.swiper-container)

How to create a space between cards using bootstrap in React while mapping description of cards

Right now all the cards are aligned in a row but my goal is to create a small space between them.
I'm trying to create a fake Skateboarding eCommerce website. I started with the bearings (the part that goes inside the skateboard wheel to help it rotate). I successfully added all the cards to the page but find manipulating margin on the card with "m-1" using bootstrap adds a margin to the right side of the page for some reason and takes away some of the space that should be used up by the card.
enter code here
import React from 'react';
import { Button, Card } from 'react-bootstrap';
import 'bootstrap/dist/css/bootstrap.min.css';
import bearingsData from './Product/bearingsData';
const Bearings = () => {
return (
<div className="main">
<div className="title">
<h1>Bearings</h1>
</div>
<div className="container " >
<div className="row">
{ bearingsData.map(product => {
return (
<Card className="col-xs-12 col-sm-6 col-md-4 col-lg-3 p-4 " key={ product.id }>
<Card.Img src={ product.image }/>
<Card.Body>
<Card.Title>
{ product.brand }
</Card.Title>
<Card.Text>
{ product.name }
</Card.Text>
<Button> Add to Shopping Cart</Button>
</Card.Body>
</Card>
);
})}
</div>
</div>
</div>
)
}
export default Bearings;

How to detect if the user has clicked on the arrows in react-multi-carousel?

How can I detect if the user has clicked the previous/next arrow to toggle the value of the autoplay in react-multi-carousel?
return (
<Carousel
autoPlay={true}
autoPlaySpeed={4500}
customTransition="all .5"
transitionDuration={300}
infinite={true}
>
{movies.map((movie) => (
<img
key={movie.id}
style={{ width: "100%", height: "100%" }}
src={movie.image}
alt={movie.title}
/>
))}
</Carousel>
If you're curious about anything called when the page switches,
When you see the documentation for that 'react-multi-carousel',
There is a callback fuction called when a page is converted.
here
<Carousel
afterChange={(previousSlide, { currentSlide, onMove }) => {
doSpeicalThing();
}}
beforeChange={(nextSlide, { currentSlide, onMove }) => {
doSpeicalThing();
}}
/>
As Changoon Lee mentioned in their answer, you can use the beforeChange and afterChange callbacks which are invoked each time before and after a sliding.
If you only want to detect button clicks (and not keyboard slides or drags), you can create new button components and pass them as custom arrows. Your custom buttons will receive a list of props/state; one of them is the react-multi-carousel's onClick handler.
You can pass your custom buttons to the Carousel as props (customLeftArrow and customRightArrow).
function CustomRightArrow({ onClick }) {
function handleClick() {
// do whatever you want on the right button click
console.log('Right button clicked, go to next slide');
// ... and don't forget to call onClick to slide
onClick();
}
return (
<button
onClick={handleClick}
aria-label="Go to next slide"
className="react-multiple-carousel__arrow react-multiple-carousel__arrow--right"
/>
);
}
function App() {
return (
<Carousel
customLeftArrow={<CustomLeftArrow />}
customRightArrow={<CustomRightArrow />}
infinite
keyBoardControl
>
{images.map((image, i) => {
return (
<img
key={i}
style={{ width: '100%', height: '100%' }}
src={image}
alt=""
/>
);
})}
</Carousel>
);
}

How to Update content using ReactJS

I'm new in React and I trying to build a simple list of items clickable to get data and update the DOM, I have a list of links on render()
const listNews = this.state.news.map((item, i) =>
<ListGroupItem key={i} className="font-size-1 text-left">
<a href='#' onClick={() => this.getInfoNews(i)}>{item.title}</a>
</ListGroupItem>
);
the function "getInfoNews(i)" have this piece of code to display the data into DOM
getInfoNews(i){
var content = {
news : this.state.news[i]
}
console.log(content.news)
if(content.news === undefined){
return (
<Card>
<CardBody>
<CardTitle>Card Title</CardTitle>
<CardSubtitle>Card subtitle</CardSubtitle>
<CardText>Some quick example text to build on the card title and card's content.</CardText>
</CardBody>
</Card>
)
}else{
return (
<Card>
<CardBody>
<div className="container">
<img src={content.news.urlToImage} className="w-100" />
<CardTitle>
<div className="bottom-left font-size-2 bg-dark w-50 p-2 text-uppercase text-left">{content.news.title}</div>
</CardTitle>
</div>
<CardSubtitle className="text-right text-dark font-size-1 mr-4">
by {content.news.author ? content.news.author : "Anonymous"} , published at {content.news.publishedAt}
</CardSubtitle>
<CardText className="text-dark font-size-2 mt-4">
{content.news.description} read more
</CardText>
</CardBody>
</Card>
)
}
}
Work perfect on load first time, but dont work once clicked on every link, the data is loaded but the DOM dont update, some one can help me ? thanks!
React re-renders whenever there is an update to either the state or the props.
For example, you can load new data from API, and then do this.setState to update the component state. Then, react will re-render the component automatically.

Categories