react-multi-carousel is not rendering - javascript

I'm getting data from the state. Now I want to make a carousel slider using react-multi-carousel
I am trying to implement https://www.npmjs.com/package/react-multi-carousel for a news card component that has data coming from the API. So far my code is as follows, but the carousel does not seem to be implementing?
Child Component
import Carousel from 'react-multi-carousel';
import 'react-multi-carousel/lib/styles.css'
const responsive = {
superLargeDesktop: {
breakpoint: { max: 4000, min: 3000 },
items: 5
},
desktop: {
breakpoint: { max: 3000, min: 1024 },
items: 3
},
tablet: {
breakpoint: { max: 1024, min: 464 },
items: 2
},
mobile: {
breakpoint: { max: 464, min: 0 },
items: 1
}
};
const size = 15;
const Itemlist = props.data.slice(0, size).map((item,id) => {
return(
<div className="item px-2 col-md-3" key={item.title}>
<div className="alith_latest_trading_img_position_relative">
<figure className="alith_post_thumb">
<Link
to={{
pathname : `/details/${id}`,
}}
>
<img
alt=""
src={item.multimedia ? item.multimedia[0].url : image}
className="w-100 thumbnail"
/>
</Link>
</figure>
<div className="alith_post_title_small">
<Link
to={{
pathname : `/details/${id}`,
}}
><strong>{item.title.length > 30 ? item.title.substring(0,30) + ".." : item.title}</strong>
</Link>
<p className="meta">
<span>{`${moment(item.published_date).fromNow()}`}</span>
</p>
</div>
</div>
</div>
)
})
return (
<React.Fragment>
<Carousel responsive={responsive}>
{Itemlist}
</Carousel>
</React.Fragment>
);
};
Parent Component
state = {
items : []
}
fetchLatestNews = () => {
api.getRealFeed()
.then(response=>{
this.setState({
items : response.data.results
});
})
}
componentDidMount = () => {
this.fetchLatestNews();
}
render(){
return(
<React.Fragment>
<Item data={this.state.items}/>
</React.Fragment>
)}};

I had the same issue,
Take a look at the specific props. You can add a class to the container, slide or item for adding your css rules. In my case, I had to define a width to the containerClass.
<Carousel
containerClass="carousel-container"
itemClass="carousel-item"
>
... // Your carousel here
And in your css file:
.carousel-container {
width: 100%;
...
}

I'm not sure if this will help, but I had an issue where the carousel becomes empty when I set the prop infinity to true.
Turns out it was because the website I'm working on uses bootstrap rtl.
To fix the issue I just changed the direction of the carousel container to be ltr.
Something like this:
[dir="rtl"] .carousel-container{
direction: ltr;
}

i fix it by adding width properties to the container class
if you using tailwind u need to can set the containerClass width
<Carousel
containerClass={`w-full`}
>
{item}
</Carousel>

I believe you should add import 'react-multi-carousel/lib/styles.css' to your top-level file NOT in the child component file. E.g: _app.tsx for NextJS. It took me about 30m to find out that.

This worked fine for me in functional component: I'm late but it can be usefull to anyone in future.
https://www.npmjs.com/package/react-multi-carousel
import React, { useState } from 'react';
import Carousel from "react-multi-carousel";
import "react-multi-carousel/lib/styles.css";
const SampleCode = props => {
const [maindata, setMaindata] = useState([{'name':"one"},
{'name':"two"}]);
const responsive = {
desktop: {
breakpoint: { max: 3000, min: 1024 },
items: 3,
slidesToSlide: 3 // optional, default to 1.
},
tablet: {
breakpoint: { max: 1024, min: 464 },
items: 2,
slidesToSlide: 2 // optional, default to 1.
},
mobile: {
breakpoint: { max: 464, min: 0 },
items: 1,
slidesToSlide: 1 // optional, default to 1.
}
};
return (
<div>
<Carousel
swipeable={false}
draggable={false}
showDots={true}
responsive={responsive}
ssr={false} // means to render carousel on server-side.
infinite={true}
autoPlay={false}
autoPlaySpeed={1000}
keyBoardControl={true}
customTransition="all .5"
transitionDuration={500}
containerClass="carousel-container"
// removeArrowOnDeviceType={["tablet", "mobile"]}
//deviceType={true}//{this.props.deviceType}
dotListClass="custom-dot-list-style"
itemClass="carousel-item-padding-40-px"
className='location-jobs '
>
{
maindata.map((each) => {
return (
<div className='item p-3 mx-3 d-flex'>
{each.name}
</div>
)
})
}
</Carousel>
</div>
);
}
export default SampleCode;

It is having width issues like I was too using in my project, I have to set the width by using media queries. I don't know why the developer hasn't fixed the issue, but you can try giving a default width in inspect section and then setting up the width by using media queries.

Related

react multi carousel only showing one element per slide

I am using the react multi carousel library to display some divs. The code seems to be working in theory as you see below:
import * as React from "react";
import "../styles/Home.css";
import Carousel from "react-multi-carousel";
import "react-multi-carousel/lib/styles.css";
const responsive = {
superLargeDesktop: {
// the naming can be any, depends on you.
breakpoint: { max: 4000, min: 3000 },
items: 5
},
desktop: {
breakpoint: { max: 3000, min: 1024 },
items: 5
},
tablet: {
breakpoint: { max: 1024, min: 464 },
items: 5
},
mobile: {
breakpoint: { max: 464, min: 0 },
items: 5
}
};
const IndicatorCarousel = () => {
return (
<div className="IndicatorCarousel">
<div className="IndicatorCarouselText">
Select your preferred stock indicators
</div>
<br></br>
<Carousel
swipeable={false}
draggable={false}
showDots={true}
responsive={responsive}
ssr={true} // means to render carousel on server-side.
infinite={true}
autoPlaySpeed={1000}
keyBoardControl={true}
customTransition="all .5"
transitionDuration={500}
containerClass="carousel-container"
removeArrowOnDeviceType={["tablet", "mobile"]}
dotListClass="custom-dot-list-style"
itemClass="carousel-item-padding-40-px"
>
<div className="IndicatorCarouselCard">
Test
</div>
<div className="IndicatorCarouselCard">
Test2
</div>
<div className="IndicatorCarouselCard">
test3
</div>
<div className="IndicatorCarouselCard">
test4
</div>
<div className="IndicatorCarouselCard">
test5
</div>
</Carousel>
</div>
);
};
export default IndicatorCarousel;
However, when I render the carousel in my browser, it only shows three sections with a singular div in each section and is able to be navigated using the dots and arrows. Instead, I would like to display all three sections at the same time and move along the carousel using the arrows.
Does anybody see something wrong in my code?
Let me know.
Current situation:
Try setting the centerMode property to true on the Carousel component.
<Carousel
...
centerMode={true}
...
>
Alternatively you could try setting partialVisible to true

React Image Magnifiers not working when zoom in using nextjs

I want to make image zoom in when hover and using this plugin react-image-magnifiers usually it's fine when i make without next.js but when i using next.js just showing image and when i try to hover my mouse to the image, and then zoom in not working, maybe there is any mistake in my next.config.js ?
This is my next.config.js
const withPlugins = require('next-compose-plugins');
const withCss = require('#zeit/next-css');
const withSass = require('#zeit/next-sass');
const withImages = require('next-images');
const nextSettings = {
exportTrailingSlash: true,
exportPathMap: function() {
return {
'/': { page: '/' },
};
},
};
module.exports = withPlugins([[withSass(withCss({
webpack: function (config) {
config.module.rules.push({
test: /\.(eot|woff|woff2|ttf|svg|png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
limit: 100000,
name: '[name].[ext]'
}
}
})
return config
}
})), withImages()]]);
And this is my Gallery.jsx
import React from "react";
import Slider from "react-slick";
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";
import { SideBySideMagnifier } from "react-image-magnifiers";
export default function GallerySide (props) {
const dataImage = props.product;
const [state, setState] = React.useState({
alwaysInPlace: false,
overlayOpacity: 0.6,
switchSides: false,
fillAvailableSpace: false,
fillAlignTop: false,
fillGapLeft: 0,
fillGapRight: 10,
fillGapTop: 10,
fillGapBottom: 10,
largeImage: dataImage[0].largeImage,
});
const {
alwaysInPlace,
overlayOpacity,
switchSides,
fillAvailableSpace,
fillAlignTop,
fillGapLeft,
fillGapRight,
fillGapTop,
fillGapBottom,
largeImage
} = state;
const ArrowLeft = (props) => (
<a href="#disabled" {...props} className="grist-prev">
<i className="fas fa-chevron-left"></i>
</a>
);
const ArrowRight = (props) => (
<a href="#disabled" {...props} className="grist-next">
<i className="fas fa-chevron-right"></i>
</a>
);
const settings = {
dots: false,
infinite: true,
speed: 500,
slidesToShow: 4,
slidesToScroll: 1,
prevArrow: <ArrowLeft />,
nextArrow: <ArrowRight />,
};
const ChangeSlider = (event) => {
setState({
alwaysInPlace: false,
overlayOpacity: 0.6,
switchSides: false,
fillAvailableSpace: false,
fillAlignTop: false,
fillGapLeft: 0,
fillGapRight: 10,
fillGapTop: 10,
fillGapBottom: 10,
largeImage: event,
});
}
return (
<>
<SideBySideMagnifier
className="grist-input-position"
style={{ order: switchSides ? "1" : "0" }}
imageSrc={largeImage}
largeImageSrc={largeImage}
alwaysInPlace={alwaysInPlace}
overlayOpacity={overlayOpacity}
switchSides={switchSides}
zoomPosition="left"
inPlaceMinBreakpoint={641}
fillAvailableSpace={fillAvailableSpace}
fillAlignTop={fillAlignTop}
fillGapTop={fillGapTop}
fillGapRight={fillGapRight}
fillGapBottom={fillGapBottom}
fillGapLeft={fillGapLeft}
zoomContainerBorder="1px solid #ccc"
cursorStyle="zoom-in"
/>
<div className="col-12 mt-2">
<div className="col-11 mx-auto">
<Slider {...settings}>
{dataImage.map((data, index) =>
<a href="#disabled" key={index} onClick={() => ChangeSlider(data.largeImage)}>
<div className="card m-2">
<div className="card-body p-0">
<img src={data.thumbImage} width="100%" alt="Grist" />
</div>
</div>
</a>
)}
</Slider>
</div>
</div>
</>
);
}
I hope there is a solution for this or another way to make like this.
UPDATE :
i solved the problem, it because i have scss call "typhography.scss" and make tag "img" max-width: 100%, because of that my image always set 100% of width, by disable or remove this line
img {
max-width: 100%;
}
it's work perfectly, thanks.
i solved the problem, it because i have scss call "typhography.scss" and make tag "img" max-width: 100%, because of that my image always set 100% of width, by disable or remove this line
img {
max-width: 100%;
}
it's work perfectly.
The right answer is the one marked as correct.
To disable in a general way use this css rule:
img {
max-width: unset !important;
}

React functional component TypeError: Cannot read property 'props' of undefined

After hours reading how to bind this I give up. This is my first time with react, I have reviewed over 20 related questions on stackoverflow but I could not solve my problem.
I have installed react-multi-carousel component following the guidelines.
I have simply copied and pasted the Common Usage code and I am getting this annoying error:
TypeError: Cannot read property 'props' of undefined
Index
src/views/Index.js:107
104 | responsive={responsive}
105 | ssr={true} // means to render carousel on server-side.
106 | infinite={true}
> 107 | autoPlay={this.props.deviceType !== "mobile" ? true : false}
| ^ 108 | autoPlaySpeed={1000}
109 | keyBoardControl={true}
110 | customTransition="all .5"
I tried to follow almost all the answers I found (mainly binding the this) without success.
Here is my code:
import React from "react";
// reactstrap components
import {
Container
} from "reactstrap";
import Carousel from 'react-multi-carousel';
import 'react-multi-carousel/lib/styles.css';
// core components
import ScrollTransparentNavbar from "components/Navbars/ScrollTransparentNavbar.js";
import IndexHeader from "components/Headers/IndexHeader.js";
const responsive = {
desktop: {
breakpoint: { max: 3000, min: 1024 },
items: 3,
slidesToSlide: 3, // optional, default to 1.
},
tablet: {
breakpoint: { max: 1024, min: 464 },
items: 2,
slidesToSlide: 2, // optional, default to 1.
},
mobile: {
breakpoint: { max: 464, min: 0 },
items: 1,
slidesToSlide: 1, // optional, default to 1.
},
};
function Index() {
React.useEffect(() => {
document.body.classList.add("index-page");
document.body.classList.add("sidebar-collapse");
document.documentElement.classList.remove("nav-open");
window.scrollTo(0, 0);
document.body.scrollTop = 0;
return function cleanup() {
document.body.classList.remove("index-page");
document.body.classList.remove("sidebar-collapse");
};
});
return (
<>
<ScrollTransparentNavbar />
<div className="wrapper">
<IndexHeader />
<Carousel
swipeable={false}
draggable={false}
showDots={true}
responsive={responsive}
ssr={true} // means to render carousel on server-side.
infinite={true}
autoPlay={this.props.deviceType !== "mobile" ? true : false}
autoPlaySpeed={1000}
keyBoardControl={true}
customTransition="all .5"
transitionDuration={500}
containerClass="carousel-container"
removeArrowOnDeviceType={["tablet", "mobile"]}
deviceType={this.props.deviceType}
dotListClass="custom-dot-list-style"
itemClass="carousel-item-padding-40-px">
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
<div>Item 4</div>
</Carousel>
</div>
</div>
</>
);
}
export default Index;
You didn't define props
there is no need for this in functional component
const Index = (props) => { ...
// or
function Index(props) {...
autoPlay={props.deviceType ...
In your function component you should add props like this
function Index(props) {
...
}
A function component does not get its props via this.props, it gets them as an object which is the first parameter of the function.
function Index (props) {
// ...
return (
// ...
autoPlay={props.deviceType !== mobile}
)
}

Return back to first slide when carousel reaches last

I am using https://www.npmjs.com/package/react-multi-carousel in react js project.
The carousel is working as expected but I am in the need to make the carousel to start from first when it reaches the last slide.
Complete working example: https://codesandbox.io/s/react-multi-carousel-playground-2c6ye
Code:
<Carousel
ssr
deviceType={deviceType}
itemClass="image-item"
responsive={responsive}
>
I have added like this,
<Carousel
infinite={true}
autoPlay={true}
autoPlaySpeed={3000}
ssr
deviceType={deviceType}
itemClass="image-item"
responsive={responsive}
>
But it automatically creates infinite number of slides but that is not my requirement.. Once it reaches the end then it should get back to first slide after 1 second duration because user needs to move backward n number of times to reach the first slide.
Kindly help me to start from beginning slide once the carousel once it reaches last slide(With some delay like 1000ms so that user can see the last slide for 1s and can view the first after that..
You can achieve this by writing your own autoloop and by using custom buttons. Honnestly, maybe you should just pick another library that does what you want. But you educationnal purpose, I did an example of what you should have done. Please note that you need to add the CSS for the new button group.
import React, { useEffect, useRef } from "react";
import { render } from "react-dom";
import Carousel from "react-multi-carousel";
import "react-multi-carousel/lib/styles.css";
const responsive = {
desktop: {
breakpoint: { max: 3000, min: 1024 },
items: 1,
paritialVisibilityGutter: 60
},
tablet: {
breakpoint: { max: 1024, min: 464 },
items: 1,
paritialVisibilityGutter: 50
},
mobile: {
breakpoint: { max: 464, min: 0 },
items: 1,
paritialVisibilityGutter: 30
}
};
const images = [
"https://images.unsplash.com/photo-1549989476-69a92fa57c36?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60",
"https://images.unsplash.com/photo-1549396535-c11d5c55b9df?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60",
"https://images.unsplash.com/photo-1550133730-695473e544be?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60"
];
/* ADD THIS LINE */
// Your custom Button group. CSS need to be added
const ButtonGroup = ({ next, previous, goToSlide, ...rest }) => {
const {
carouselState: { currentSlide }
} = rest;
const lastImageIndex = images.length - 1;
return (
<div className="carousel-button-group" style={{ position: "absolute" }}>
<button
onClick={() =>
currentSlide === 0 ? goToSlide(lastImageIndex) : previous()
}
>
Prev
</button>
<button
onClick={() =>
currentSlide === lastImageIndex ? goToSlide(0) : next()
}
>
Next
</button>
</div>
);
};
/* TO THIS LINE */
const Simple = ({ deviceType }) => {
/* ADD THIS LINE */
const carousel = useRef(null);
const lastImageIndex = images.length - 1;
useEffect(() => {
const autoloop = setInterval(() => {
if (carousel.state.currentSlide === lastImageIndex) {
carousel.goToSlide(0);
} else {
carousel.next();
}
}, 3000); // Your custom auto loop delay in ms
return () => clearInterval(autoloop);
}, []);
/* TO THIS LINE */
return (
<Carousel
ssr
deviceType={deviceType}
itemClass="image-item"
responsive={responsive}
/* ADD THIS LINE */
ref={el => (carousel = el)}
arrows={false}
customButtonGroup={<ButtonGroup />}
/* TO THIS LINE */
>
{images.slice(0, 5).map((image, index) => {
return (
<div key={index} style={{ position: "relative" }}>
<img
draggable={false}
alt="text"
style={{ width: "100%", height: "100%" }}
src={image}
/>
<p
style={{
position: "absolute",
left: "50%",
bottom: 0,
color: "white",
transform: " translateX(-50%)"
}}
>
Legend:{index}.
</p>
</div>
);
})}
</Carousel>
);
};
render(<Simple />, document.getElementById("root"));
Hope it helps. Happy coding :)
I believe the best option now is to use this prop:
infiniteLoop: true
Reference: https://github.com/leandrowd/react-responsive-carousel/issues/232
The simplest solution to this problem is to add infiniteloop props as true.
<Carousel infiniteLoop={true} autoPlay={true} interval={1000}>
<div>
<img src={slider1} />
<p className='legend'>Legend 1</p>
</div>
<div>
<img src={slider2} />
<p className='legend'>Legend 2</p>
</div>
</Carousel>

how to show image slider in React

I am using this plugin https://github.com/akiran/react-slick for image slider but for some reason i am unable to achieve what I want.
Here is a sample code:
import React, { Component } from "react";
import Slider from "../src/slider";
import { baseUrl } from "./config";
export default class CenterMode extends Component {
render() {
const settings = {
customPaging: function(i) {
return (
<a>
<img src={`${baseUrl}/abstract0${i + 1}.jpg`} />
</a>
);
},
dots: true,
dotsClass: "slick-dots slick-thumb",
infinite: true,
speed: 500,
slidesToShow: 1,
slidesToScroll: 1
};
return (
<div>
<h2>Custom Paging</h2>
<Slider {...settings}>
<div>
<img src={baseUrl + "/abstract01.jpg"} />
</div>
<div>
<img src={baseUrl + "/abstract02.jpg"} />
</div>
<div>
<img src={baseUrl + "/abstract03.jpg"} />
</div>
<div>
<img src={baseUrl + "/abstract04.jpg"} />
</div>
</Slider>
</div>
);
}
}
This works perfectly fine unless the image file names are like abstract01, abstract02, in my case image file name is random it can be anything, thus the thumbnail part does not work for me. Are there any option that I can pass some other argument on the customPaging so that i can receive src attr and can get the file name from there.
Any idea would be much appreciated here.
Note: the images in my case are coming from amazon s3, so I have no control over them at all!
I believe you can do something like this:
const images = [
{ src: baseUrl + "/abstract01.jpg" },
{ src: baseUrl + "/abstract02.jpg" },
{ src: baseUrl + "/abstract03.jpg" },
{ src: baseUrl + "/abstract04.jpg" },
];
export default class App extends Component {
render() {
const settings = {
customPaging: function (i) {
return (
<a>
<img src={images[i].src} />
</a>
);
},
dots: true,
dotsClass: "slick-dots slick-thumb",
infinite: true,
speed: 500,
slidesToShow: 1,
slidesToScroll: 1
};
return (
<div>
<h2>Custom Paging</h2>
<Slider {...settings}>
{images.map((img) => (
<div>
<img src={img.src} />
</div>
))}
</Slider>
</div>
);
}
}
Basically you can create the image array (because you already know the images) and then map through it to get the slides and use the iterator in custom paging to get the image by index from your array.

Categories

Resources