SwiperSlide onTouchStart/onClick => trigger slideNext() - reactjs

I want to include this slideshow: https://swiperjs.com/react/
As I find it not very comfortable to drag for the next slide, I want to add an onClick event to the full Slider so the next slide comes.
How can I trigger a slideNext() in React? I have problems reading the documentation / I do not understand it - and it seems the documentation does not tell how to do this in react.
In jquery it would be something like this :
$('section.slideshow').on( 'click', function() {
swiper.slideNext();
});
Here is my react code :
import React from 'react'
import SwiperCore, { Navigation, Pagination, A11y } from 'swiper'
import { Swiper, SwiperSlide } from 'swiper/react'
import 'swiper/swiper.scss'
import 'swiper/components/navigation/navigation.scss'
import 'swiper/components/pagination/pagination.scss'
SwiperCore.use([Navigation, Pagination, A11y])
function Page(){
return (
<div>
<Swiper
onClick={() => console.log('click')}
onTouchStart={() => slideNext() }
>
<SwiperSlide>slide 1</SwiperSlide>
<SwiperSlide>slide 2</SwiperSlide>
</Swiper>
</div>
);
}
export default Page;

You can opt to use the Navigation API as written in the docs
<Swiper
navigation={{
nextEl: '.next',
}}
>
<SwiperSlide className="next">slide 1</SwiperSlide>
<SwiperSlide className="next">slide 2</SwiperSlide>
<SwiperSlide className="next">slide 3</SwiperSlide>
</Swiper>
CodeSandBox: https://codesandbox.io/s/so-react-swiper-next-slide-2714t?file=/src/App.js

For React Hooks
Define a useState like this:
const [my_swiper, set_my_swiper] = useState({});
Then in your swiper define it like this:
<Swiper
slidesPerView={1}
onInit={(ev) => {
set_my_swiper(ev)
}}>
<SwiperSlide>
<div>
Slide 1
</div>
</SwiperSlide>
<SwiperSlide>
<div>
Slide 2
</div>
</SwiperSlide>
</Swiper>
Notice the onInit method to bind to your variable.
Then you can use my_swiper hook to call next/previous functions like this.
my_swiper.slideNext();
my_swiper.slidePrev();
You can call these anywhere to dynamically control your swiper.
Also you can navigate to any slide
my_swiper.slideTo(number);

I used it as below:
<Swiper
getSwiper={this.updateSwiper}
{...params}
>{/*modules={[Navigation]}*/}
{items}
</Swiper>
by these functions:
updateSwiper(value:any) {
this.setState({
swiper: value
});
}
goNext = () => {
if (this.state.swiper !== null) {
this.state.swiper.slideNext();
}
};

Related

Swiper Js cannot read properties of undefined ('reading includes)

I have this component I wrote for reviews using swiperjs in a react and nextjs project but I have been getting an error with seems to be coming from this reviews component saying Unhandled Runtime Error TypeError: Cannot read properties of undefined (reading 'includes')
I can't figure out why but when I comment out all the code in that component, everything seems to work fine. I have also tried upgrading swiper in package.json and also tried downgrading react but the error will not go away. Please help me figure out what I could be doing wrong using the code below
components/Reviews.jsx
import React, { useRef, useState, useEffect } from 'react'
import {ReviewForm} from '../components'
import { FaFacebookSquare, FaGithubSquare, FaTwitterSquare, FaInstagramSquare, FaYoutubeSquare } from 'react-icons/fa'
import {MdOutlineArrowForward} from 'react-icons/md'
import { getReviews } from '../services'
import { Swiper, SwiperSlide } from "swiper/react";
import moment from 'moment'
// Import Swiper styles
import "swiper/css";
import "swiper/css/pagination";
import "swiper/css/navigation";
// import required modules
import { Pagination, Navigation } from "swiper";
const Reviews = () => {
const [reviews, setReviews] = useState([]);
useEffect(() => {
getReviews()
.then((newReviews) => setReviews(newReviews))
}, [])
return (
<div className='reviewsBgBlack'>
<div><h4 className="font-normal py-5 tracking-wide lg:text-5xl md:text-3xl text-center text-[#D72A06]">CLIENTS REVIEWS <span className='text-white'>ABOUT <br />THE QUALITY OF OUR WORK</span></h4></div>
<Swiper
slidesPerView={1}
slidesPerGroup={1}
spaceBetween={10}
loop={false}
loopFillGroupWithBlank={true}
pagination={{
clickable: true,
}}
breakpoints={{
640:{
slidesPerView:2,
spaceBetween:10
},
768:{
slidesPerView:3,
spaceBetween:20
},
1024:{
slidesPerView:3,
spaceBetween:30
}
}}
navigation={true}
modules={[Pagination, Navigation]}
className="mySwiper"
>
{reviews.map((review) => (
<div key={review.name}>
<div className="reviewsContainer">
<div className="content">
<SwiperSlide><div className="reviewCard">
<div className="reviewCard-content">
<div className="image">
<img src="/logo.png" alt="" />
</div>
<div className='media-icons'>
<i><a href={`https://www.instagram.com/${review.instagram}`}><FaInstagramSquare /></a></i>
<i><a href={`https://www.twitter.com/${review.twitter}`}><FaTwitterSquare /></a></i>
<i><a href={`https://www.facebook.com/${review.facebook}`}><FaFacebookSquare /></a></i>
</div>
<div className="name-profession">
<span className="name">{review.name}</span>
<span className='profession font-semibold'>{review.profession}</span>
<p className="text-gray-400 mb-2 font-semibold text-xs">{moment(review.createdAt).format('MMM DD, YYYY')}</p>
<span className="profession">{review.testimonial}</span>
</div>
<div className={`button ${review.casestudy ? `visible` : `hidden`}`}>
<button>view case study<span><MdOutlineArrowForward className='mt-1 text-lg ml-2'/></span></button>
</div>
</div>
</div>
</SwiperSlide>
</div>
</div>
</div>
))}
</Swiper>
<ReviewForm />
</div>
)
}
export default Reviews
console error
next-dev.js?3515:20 The above error occurred in the <Swiper> component:
at eval (webpack-internal:///./node_modules/swiper/react/swiper.js:43:98)
at div
at Reviews (webpack-internal:///./sections/Reviews.jsx:38:62)
at div
at div
at Home (webpack-internal:///./pages/index.jsx:29:23)
at Layout (webpack-internal:///./components/Layout.jsx:11:26)
at $704cf1d3b684cc5c$export$9f8ac96af4b1b2ae (webpack-internal:///./node_modules/#react-aria/ssr/dist/module.js:23:64)
at MyApp (webpack-internal:///./pages/_app.tsx:24:27)
at ErrorBoundary (webpack-internal:///./node_modules/next/dist/compiled/#next/react-dev-overlay/dist/client.js:8:20742)
at ReactDevOverlay (webpack-internal:///./node_modules/next/dist/compiled/#next/react-dev-overlay/dist/client.js:8:23635)
at Container (webpack-internal:///./node_modules/next/dist/client/index.js:70:9)
at AppContainer (webpack-internal:///./node_modules/next/dist/client/index.js:215:26)
at Root (webpack-internal:///./node_modules/next/dist/client/index.js:406:27)
React will try to recreate this component tree from scratch using the error boundary you provided, ErrorBoundary.
in NEXT-JS maybe
reactStrictMode: false
will solve your problem
Looks like there is a bug in version 8.4
https://github.com/nolimits4web/swiper/issues/6063

swiper-button outside container in react

how can I make swiper nav outside the container in react js?
to
you can use this
method 1
//add custom btns in some inner comp
<i className="icon-arrow-long-right review-swiper-button-next"></i>
<i className="icon-arrow-long-left review-swiper-button-prev"></i>
and next in swiper comp
<Swiper
navigation={{
nextEl: '.review-swiper-button-next',
prevEl: '.review-swiper-button-prev',
}}
>
</Swiper>
or you use this way
method 2
// some-inner-component.jsx
import { React } from 'react';
import { useSwiper } from 'swiper/react';
export default function SlideNextButton() {
const swiper = useSwiper();
return (
<button onClick={() => swiper.slideNext()}>Slide to the next slide</button>
);
}
more in info :
https://swiperjs.com/react#use-swiper
enjoy ;)

How to add custom class to swiper slider on its events in React?

Here's my Swiper code:
import { Swiper, SwiperSlide } from 'swiper/react';
import { EffectFade } from 'swiper';
import 'swiper/css';
import 'swiper/css/effect-fade';
<Swiper
modules={[EffectFade]}
effect="fade"
>
{
items.map(item => <SwiperSlide key={item.id}>
<img
src={item.imageUrl}
className="h-screen object-cover transition-transform duration-[5000ms] scale-150"
/>
<div>{item.title}</div>
<div>{item.subtitle}</div>
</SwiperSlide>)
}
</Swiper>
It works like a charm. Now I want to zoom out the background image when the slide changes.
I'm using tailwind. I need to set scale-100 as the default scale for all slides, and when a slide is shown (as soon as it's about to be changed and shown) I should set scale-150 so that it would zoom out over 5 seconds.
I'm stuck at this point. I know I should use events. But how can I link that event to the current slider?
From the Swiper documentation: https://swiperjs.com/react#styles
You could use either "isVisible" or "isActive" depending on your implementation, but the below code should work.
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
import { Swiper, SwiperSlide } from 'swiper/react';
import { EffectFade } from 'swiper';
import 'swiper/css';
import 'swiper/css/effect-fade';
<Swiper
modules={[EffectFade]}
effect="fade"
>
{
items.map(item => <SwiperSlide key={item.id}>
{({ isVisible }) => (
<img
src={item.imageUrl}
className={`h-screen object-cover transition-transform duration-[5000ms] ${isVisible ? "scale-150" : ""}`}
/>
<div>{item.title}</div>
<div>{item.subtitle}</div>
)
</SwiperSlide>)
}
</Swiper>

Swiper Component not working in React and throwing Erros

So I am following along with a course by Traversy Media called "React Front To Back 2022", at the 16th section of the course in the 5th and 6th videos, he was using the Swiper component. I was following along step-by-step but at the end, it threw an error, so after a bit of thinking and googling I decided to see the solution of the GitHub repository posted by him of the project, I compared the code, seemed the same, I copied it, still, it threw the errors and didn't render the page.
I couldn't find a fix anywhere(google, documentation, youtube, etc), so hopefully someone can help me here. Thank you in advance for the help.
The Errors:
init-swiper.js:25 Uncaught TypeError: Cannot read properties of undefined (reading 'pagination')
at mountSwiper (init-swiper.js:25:1)
at swiper.js:136:1
at commitHookEffectListMount (react-dom.development.js:23049:1)
at invokeLayoutEffectMountInDEV (react-dom.development.js:25010:1)
at invokeEffectsInDev (react-dom.development.js:27304:1)
at commitDoubleInvokeEffectsInDEV (react-dom.development.js:27280:1)
at flushPassiveEffectsImpl (react-dom.development.js:27007:1)
at flushPassiveEffects (react-dom.development.js:26935:1)
at performSyncWorkOnRoot (react-dom.development.js:26032:1)
at flushSyncCallbacks (react-dom.development.js:12009:1)
react_devtools_backend.js:4026 The above error occurred in the <Swiper> component:
at http://localhost:3000/static/js/bundle.js:131862:66
at Slider (http://localhost:3000/static/js/bundle.js:1549:66)
at main
at div
at Explore
at Routes (http://localhost:3000/static/js/bundle.js:120121:24)
at Router (http://localhost:3000/static/js/bundle.js:120046:30)
at BrowserRouter (http://localhost:3000/static/js/bundle.js:118774:23)
at App
Uncaught TypeError: Cannot read properties of undefined (reading 'pagination')
at mountSwiper (init-swiper.js:25:1)
at swiper.js:136:1
at commitHookEffectListMount (react-dom.development.js:23049:1)
at invokeLayoutEffectMountInDEV (react-dom.development.js:25010:1)
at invokeEffectsInDev (react-dom.development.js:27304:1)
at commitDoubleInvokeEffectsInDEV (react-dom.development.js:27280:1)
at flushPassiveEffectsImpl (react-dom.development.js:27007:1)
at flushPassiveEffects (react-dom.development.js:26935:1)
at performSyncWorkOnRoot (react-dom.development.js:26032:1)
at flushSyncCallbacks (react-dom.development.js:12009:1)
The Code:
import { useState, useEffect } from 'react'
import { useNavigate } from 'react-router-dom'
import { collection, getDocs, query, orderBy, limit } from 'firebase/firestore'
import { db } from '../firebase.config'
import SwiperCore, { Navigation, Pagination, Scrollbar, A11y } from 'swiper'
import { Swiper, SwiperSlide } from 'swiper/react'
import 'swiper/swiper-bundle.css'
import Spinner from './Spinner'
SwiperCore.use([Navigation, Pagination, Scrollbar, A11y])
function Slider() {
const [loading, setLoading] = useState(true)
const [listings, setListings] = useState(null)
const navigate = useNavigate()
useEffect(() => {
const fetchListings = async () => {
const listingsRef = collection(db, 'listings')
const q = query(listingsRef, orderBy('timestamp', 'desc'), limit(5))
const querySnap = await getDocs(q)
let listings = []
querySnap.forEach((doc) => {
return listings.push({
id: doc.id,
data: doc.data(),
})
})
setListings(listings)
setLoading(false)
}
fetchListings()
}, [])
if (loading) {
return <Spinner />
}
if (listings.length === 0) {
return <></>
}
return (
listings && (
<>
<p className='exploreHeading'>Recommended</p>
<Swiper slidesPerView={1} pagination={{ clickable: true }}>
{listings.map(({ data, id }) => (
<SwiperSlide
key={id}
onClick={() => navigate(`/category/${data.type}/${id}`)}
>
<div
style={{
background: `url(${data.imgUrls[0]}) center no-repeat`,
backgroundSize: 'cover',
}}
className='swiperSlideDiv'
>
<p className='swiperSlideText'>{data.name}</p>
<p className='swiperSlidePrice'>
${data.discountedPrice ?? data.regularPrice}{' '}
{data.type === 'rent' && '/ month'}
</p>
</div>
</SwiperSlide>
))}
</Swiper>
</>
)
)
}
export default Slider
GitHub link to the repo
I'm currently facing same issue while following the course On udemy can't seem to find any difference in my code. The fix was, I updated Swiper to the latest version using npm i swiper#latest then changed my imports to import {Navigation, Pagination, Scrollbar, A11y } from 'swiper'
import { Swiper, SwiperSlide } from 'swiper/react'
import 'swiper/css'
and finally updated my swiper components to <Swiper
slidesPerView={1}
pagination={{ clickable: true }}
modules={[Navigation, Pagination, Scrollbar, A11y]}
navigation
scrollbar={{ draggable: true }}
>
{listing.imgUrls.map((url, index) => (
<SwiperSlide key={index}>
<div
style={{
background: `url(${listing.imgUrls[index]}) center no-repeat`,
backgroundSize: 'cover',
minHeight: '26rem',
}}
className='swiperSlideDiv'
></div>
</SwiperSlide>
))}
</Swiper>
Try switching versions for switcher package.
Checkout the package.json of traversary's repo: https://github.com/bradtraversy/house-marketplace/blob/main/package.json
Its coming due to <react.strictmode> remove it from index.js and it works but I don't know why strict mode causes this error

React how to update array useState on button click

I have seen a hundred videos and read about this, and it still doesn't make sense to me. I'm trying to update an array on a button click but when I log out the items array, it's one behind, meaning it's not reactive and gets added on the next paint. Also, I wrapped my Employee component inside a div only to be able to add an 'onClick' to it. Ideally, I'd like the onClick to be on the Employee component itself, but it doesn't work. Thanks.
import React, {ReactElement, useState } from "react";
import {TextContainer, Text } from "react-md";
import model from '../Models'
import Employee from './Employee/Employee'
import styles from '../home.module.scss'
export default function Home(): ReactElement {
const [items, setItems] = useState<Array<any>>([]);
const addItem = (val:any) => {
setItems([...items, val ])
console.log('items :', items)
}
return (
<div className='center'>
<TextContainer className='center'>
<Text type='headline-4' style={{color: 'white'}}>Employee List</Text>
</TextContainer>
<section className={styles.emp_list}>
{model.map((props, index) =><div key={index} onClick={() => addItem(props.name)}><Employee key={index} name={props.name} role={props.role} markets={props.markets} image={props.image}/></div>)}
</section>
</div>
)}
And my Employee component:
import React from "react";
import {MediaContainer} from "#react-md/media";
import styles from './employee.module.scss'
import { Card, CardContent, CardHeader} from "react-md";
function Employee(props: any) {
return (
<Card className={styles.emp_card}>
<CardHeader>
<div className={styles.emp_text}>
<p key={props.name}>Name: {props.name}</p>
<p key={props.role}>Title: {props.role}</p>
<p key={props.markets}>Markets: {props.markets[0]} {props.markets[1] && <span>and {props.markets[1]}</span>}</p>
</div>
</CardHeader>
<CardContent>
<MediaContainer>
<img key={props.image} src={props.image} alt="employee"/>
</MediaContainer>
</CardContent>
</Card>
)
}
export default Employee;
I don't think the documentation is clear enough on this, but if you want to setState using the previous state, then you should pass a function to useState. For example:
const addItem = (val:any) => {
setItems(prevItems => [...prevItems, val ])
}
https://reactjs.org/docs/hooks-reference.html#functional-updates

Resources