I admit I am very new to React and still getting my head around things, but I am using the react-lightbox-component to display images in a grid and that works just fine but the onClick event doesn't do anything then it calls the toggleLightBox function.
I know the onClick is working as I tested it against a simple console.log, what am I missing to be able to display the image in a lightbox when clicked?
const App = ({ compile }) => (
<div style={{margin: 20}}>
<header style={{textAlign: "center"}}>
<h1><Words animate>Art</Words></h1>
</header>
<body>
<h3>Android</h3>
</body>
<Lightbox
images={androidimages}
renderImageFunc={(idx, image, toggleLightbox, width, height) => {
return (
<img
key={idx}
src={image.src}
style={{width: '150px', height: '200px', margin: '20px'}}
onClick={
toggleLightbox.bind(null, idx)
}
/>
)
}
}
/>
</div>
);
Related
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>
);
}
I'm developing a reactjs project with ant-design (antd). I'm using Carousel component with auto scrolling through some photos. I also want to add some arrows to change photos manually.
I found a way to make small buttons to the left and to the right of my Carousel. But I don't get how to make them bigger (with the same height as the photos for example), move on the photos or make visible any time (now they stay hidden until the mouse cursor is exactly on them).
Here's some code:
const RightArrow = () => {
return (
<Button icon={<RightCircleOutlined/>} size="middle"/>
)
}
const LeftArrow = () => {
return (
<Button icon={<LeftCircleOutlined/>} size="middle"/>
)
}
const SSOverview = () => {
return (
<Content style={{width: "100%", padding: '0 30px', fontSize: 16}}>
<Col><Title level={1}> My Title </Title></Col>
<Carousel autoplay autoplaySpeed={7000}
draggable={true} arrows={true}
prevArrow={LeftArrow()}
nextArrow={RightArrow()}>
<div><img src={Slide2} style={{width: '100%'}} alt="Photo 1"/></div>
<div><img src={Slide1} style={{width: '100%'}} alt="Photo 2"/></div>
<div><img src={Slide3} style={{width: '100%'}} alt="Photo 3"/></div>
<div><img src={Slide4} style={{width: '100%'}} alt="Photo 4"/></div>
<div><img src={Slide5} style={{width: '100%'}} alt="Photo 5"/></div>
</Carousel>
//the rest of the page
</Content>
)
};
You can override antd default styling with custom CSS styling. To make the buttons bigger, just add style property (or add className property and style inside CSS file). For example, you could do something like this:
<Button
style={{padding: "1rem", height: "auto", width: "auto"}}
icon={<RightCircleOutlined style={{fontSize: 60}} />}
/>
Here's a pen:
https://codepen.io/jaycodist/pen/mdPyqNW
I am using https://www.npmjs.com/package/react-multi-carousel in one of my react project and I have implemented it and it works fine.
I am now in the need to implement the text (legend) over the carousel exactly like https://codesandbox.io/s/lp602ljjj7 which uses another package but I need that scenario and not that package because my need is different (Using nextjs so multi-carousel supports ssr and hence using it).
My only need is need to know how to implement the legend text over the carousel image using react-multi-carousel.
My code example: https://codesandbox.io/s/react-multi-carousel-playground-bt3v7
Change the structure of the return statement to the following structure.
Then you can store the value of the legend in the image array and pass the value to the p tag
const Simple = ({ deviceType }) => {
return (
<Carousel
ssr
partialVisbile
deviceType={deviceType}
itemClass="image-item"
responsive={responsive}
>
{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>
);
};
export default Simple;
Live demo
You should change array structure like below.
const images = [
{
image: "https://images.unsplash.com/photo-1549989476-69a92fa57c36?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60",
text: "First image",
}
];
Then inside loop just add text and style it our way!
const Simple = ({ deviceType }) => {
return (
<Carousel
ssr
partialVisbile
deviceType={deviceType}
itemClass="image-item"
responsive={responsive}
>
{images.map(image => {
return (
<div>
<img
draggable={false}
alt="text"
style={{ width: "100%", height: "100%" }}
src={image.image}
/>
{/* Have to style so this should see over the image */}
<span>{image.text}</span>
</div>
);
})}
</Carousel>
);
};
I'm recently using react-spring and it works really well but I'm having some issues when I have to apply an onClick on childs.
Here is my main structure:
<anim.button className="c"
style={{ opacity: opacity.interpolate(o => 1 - o), transform }}>
<Bar />
</anim.button>
<anim.button className="c"
style={{ opacity, transform: transform.interpolate(t => `${t}
rotateX(180deg)`) }}>
<Bar />
</anim.button>
An onClick on the anim.button would work perfectly fine of course, but that's not what I'm trying.
Here is my <Bar /> component:
const Bar = () => (
<div className="bar">
<Checkbox
onClick={() => {
set(state => !state)
}}
/>
</div>
)
I also tried using the <anim.div> instead of an <anim.button> but this gives me the same results.
Now the problem here is that it seems like react-spring puts a layer onto my <Bar /> component. Is there a way to use the onClick in my component instead of the one that is used onto anim.button?
Given that Checkbox is also a component and it might not have onClick handled try putting onClick on the wrapping div or inspect the Checkbox component.
Haven't used react-spring ever but structuring your Bar component like this may do the trick.
const Bar = (props) => (
<div onClick={() => {set(state => !state)}}>
<anim.button {...props}>
<div className="bar">
<Checkbox />
</div>
</anim.button>
</div>)
then rendering it like this:
<Bar className={'c'} style={{ opacity: opacity.interpolate(o => 1 - o), transform}}/>
<Bar className="c" style={{ opacity, transform: transform.interpolate(t => `${t}
rotateX(180deg)`) }}/>
You could rather wrap the Bar in a div: <animated.div> you are wrapping a button around a checkbox which is not great. onClick will trigger as expected.
<animated.div className="c"
style={{ opacity, transform: transform.interpolate(t => `${t}
rotateX(180deg)`) }}>
<Bar />
</animated.div>
Issue has been found and didn't actually has anything to do with react-spring.
The position absolute styling was causing this.
I am trying to grab the maxresdefault of multiple YouTube thumbnails. Some YouTube videos simply don't have a high res thumbnail photo so I want to catch that with an onError prop on an img element. For some reason my function is not triggering when I get the 404 img error. Any ideas? Thanks in advance.
class FeaturedVideo extends Component<Props> {
addDefaultSrc = (e) => {
e.target.src = this.props.background.replace("maxresdefault", "hqdefault")
}
renderVideo = (props) => (
<div
style={{
width: "100%",
height: "100%",
backgroundSize: "contain",
}}
className="featured-community-video"
>
<img onError={this.addDefaultSrc} src={props.background} alt="" />
<div className="featured-community-video-title">
<h2 style={{ fontSize: "0.8em" }}>WATCH</h2>
<h1 style={{ fontSize: props.titleFontSize }}>{props.title}</h1>
</div>
</div>
)
render() {
return (
<div
key={this.props.postId}
style={{
width: this.props.width,
height: "50%",
}}
className="featured-community-video-container"
>
<Link to={routeCodes.POST_DETAILS(this.props.postId)}>
{this.renderVideo(this.props)}
</Link>
</div>
)
}
}
To achieve this, I would suggest rendering the <img /> based on the state of your <FeatureVideo/> component.
You could for instance, create an Image object, attempt to load the background image and by this, reliably determine if the image fails to load. On the images success or failure to load, you would then setState() on your <FeaturedVideo/> component with the appropriate background value which would instead be used to rendering you actual <img/> element:
class FeaturedVideo extends Component<Props> {
componentDidMount() {
if(this.props.background) {
// When component mounts, create an image object and attempt to load background
fetch(this.props.background).then(response => {
if(response.ok) {
// On success, set the background state from background
// prop
this.setState({ background : this.props.background })
} else {
// On failure to load, set the "default" background state
this.setState({ background : this.props.background.replace("maxresdefault", "hqdefault") })
}
});
}
}
// Update the function signature to be class method to make state access eaiser
renderVideo(props) {
return <div
style={{
width: "100%",
height: "100%",
backgroundSize: "contain",
}}
className="featured-community-video">
{/* Update image src to come from state */}
<img src={this.state.background} alt="" />
<div className="featured-community-video-title">
<h2 style={{ fontSize: "0.8em" }}>WATCH</h2>
<h1 style={{ fontSize: props.titleFontSize }}>{props.title}</h1>
</div>
</div>
}
render() {
return (
<div
key={this.props.postId}
style={{
width: this.props.width,
height: "50%",
}}
className="featured-community-video-container"
>
<Link to={routeCodes.POST_DETAILS(this.props.postId)}>
{this.renderVideo(this.props)}
</Link>
</div>
)
}
}
Hope that helps!