Toggle icon with error in reactjs. How to solve? - reactjs

By clicking on the heart icon I want to change the color to red and add it to the favorite. When clicking again, it goes back to gray and remove from favorite. But when I click on an icon they all change color. How to fix to change only the icon that was clicked?
const Destaques = () => {
const { destaques, favoriteList, setFavoriteList, isFavorite, setIsFavorite, handlerIcon } = useContext(MoviesContext);
const [showStatus, setShowStatus] = useState(false);
const handleShow = () => setShowStatus(true);
const handleClose = () => setShowStatus(false);
var settings = {
infinite: false,
autoplay: true,
speed: 500,
slidesToShow: 4,
infinite: true,
slidesToScroll: 1,
initialSlide: 0,
responsive: [
{
breakpoint: 1024,
settings: {
slidesToShow: 3,
slidesToScroll: 1,
infinite: true,
}
},
{
breakpoint: 600,
settings: {
slidesToShow: 2,
slidesToScroll: 1,
initialSlide: 2
}
},
{
breakpoint: 480,
settings: {
slidesToShow: 1,
slidesToScroll: 1
}
}
]
};
const filteredHighlight = destaques.filter(movie => movie.highlight === true);
const sliders = () => {
return filteredHighlight.map((data) => {
return (
<div>
<div className='container-card' key={data.id}>
<div className='card-img'>
<img alt={data.title} src={data.poster} onClick={handleShow} />
<i onClick={handlerIcon}>
{isFavorite ?
<FaHeart className='heartIcon' style={{ color: 'red' }} /> : <FaHeart className='heartIcon' style={{ color: '#BABABA' }} />
}
</i>
</div>
<div className='box-content'>
<div className='box-title-vote'>
<h4 className='card-title'>
{data.title}
</h4>
<div className='box-vote-like'>
<span className='card-vote-average'>4/5</span>
<i className='icon-like-destaques'>
<img src={IconLike} alt="icon like"></img>
</i>
</div>
</div>
<p className='card-overview'>
{data.overview}
</p>
</div>
</div>
<Modal show={showStatus} onHide={handleClose} backdrop="static" centered >
<Modal.Header closeButton>
</Modal.Header>
<Modal.Body >
<DefaultDetail id={data.id} poster={data.poster} overview={data.overview} title={data.title} />
</Modal.Body>
</Modal>
</div>
);
});
}
return (
<div>
<h3 className='title-destaque'>Destaques</h3>
<Slider {...settings}>
{sliders()}
</Slider>
</div>
);
}
export default Destaques
Before clicking the icon
After clicking the icon
Code to add, remove and toggle icon favorite.
const MoviesContextProvider = props => {
const results = dataAllMovies.movies;
const [destaques, setDestaques] = useState(results);
const [allMovies, setAllMovies] = useState(results);
const [isFavorite, setIsFavorite] = useState(false);
const [favoriteList, setFavoriteList] = useState([]);
//favorite
const getMovieStorage = () => {
if (localStorage.getItem("favorites")) {
let favoriteList = JSON.parse(localStorage.getItem("favorites"));
return favoriteList
}
else {
let favoriteList = []
return favoriteList
}
}
useEffect(() => {
if (favoriteList.includes(allMovies.id)) {
setIsFavorite(!isFavorite);
const favorite = getMovieStorage();
setFavoriteList(favorite);
}
}, []);
const handlerIcon = (e) => {
setIsFavorite(!isFavorite);
if (isFavorite) {
var index = favoriteList.indexOf(allMovies.id);
favoriteList.splice(index, 1);
setFavoriteList(favoriteList);
deleteMovie(allMovies.id);
}
else {
setFavoriteList(favoriteList.concat([allMovies.id]));
addMovie(allMovies.id);
}
}
const deleteMovie = (id) => {
const Favorite = getMovieStorage();
var index = Favorite.indexOf(id)
Favorite.splice(index, 1);
localStorage.setItem("FavoritList", JSON.stringify(Favorite));
}
const addMovie = (id) => {
const Favorite = getMovieStorage();
Favorite.push(id)
localStorage.setItem("FavoritList", JSON.stringify(Favorite))
}
return (
<MoviesContext.Provider value={{ allMovies, destaques, filterMovies, filteredMovies, isFavorite, setIsFavorite, addFavoriteMovie, removeFavoriteMovie, handleFavClick, handlerIcon, favoriteList, getMovieStorage }}>
{props.children}
</MoviesContext.Provider>
);
}
export default MoviesContextProvider
PLEASE HELP ME. I NEED TO SOLVE THIS PROBLEM.

You must have an array of movies ids and check it with each movie id, now you check isFavorite, is not true
change isFavorite condition to => favoriteList.includes(data.id)
and fill favoriteList with movies ids in your context
<div className='card-img'>
<img alt={data.title} src={data.poster} onClick={handleShow} />
<i onClick={handlerIcon}>
{favoriteList.includes(data.id) ?
<FaHeart className='heartIcon' style={{ color: 'red' }} /> : <FaHeart className='heartIcon' style={{ color: '#BABABA' }} />
}
</i>
</div>

Related

react component animated using transition group does not display recieved property correctly

I'm trying to add some simple fade animations to component which displays information about marvel character chosen in another component (characters list). When I use in my component (BasicCharacterInfo), it is being rendered multiple times and besides on first render it displays comics and then it rerenders instantly without comics.
Here is code:
import { Skeleton } from '#mui/material';
import { useEffect, useState } from 'react';
import { Link } from 'react-router-dom';
import Transition from 'react-transition-group/Transition';
import useMarvelService from '../../services/MarvelService';
import ErrorMessage from '../errorMessage/ErrorMessage';
import './charInfo.scss';
// Creating element with photo and description of character
function BasicCharacterInfo({
data: {
name,
description,
thumbnail,
urls: { charHomePage, charWikiPage },
comics,
},
}) {
const [readyToDisplay, setReadyToDisplay] = useState(() => false);
console.log('COMICS === ' + comics.length);
useEffect(() => setReadyToDisplay(true), []);
let descriptionToDisplay;
if (description) {
const splitDescription = description.split(' ');
if (splitDescription.length >= 124) {
descriptionToDisplay = splitDescription.splice(0, 124).join(' ');
}
descriptionToDisplay = description;
}
const transitionStyles = {
entering: { opacity: 1, transition: 'all 200ms ease' },
entered: { opacity: 1, transition: 'all 200ms ease' },
exiting: { opacity: 0, transition: 'all 200ms ease' },
exited: { opacity: 0, transition: 'all 200ms ease' },
};
return (
<Transition
in={readyToDisplay}
timeout={{ enter: 100, exit: 500 }}
mountOnEnter
unmountOnExit
>
{state => (
<div style={{ ...transitionStyles[state] }}>
<div className="char__basics">
<img src={thumbnail} alt={name} />
<div>
<div className="char__info-name">{name}</div>
<div className="char__btns">
<a href={charHomePage} className="button button__main">
<div className="inner">homepage</div>
</a>
<a href={charWikiPage} className="button button__secondary">
<div className="inner">wiki</div>
</a>
</div>
</div>
</div>
<div className="char__descr">
{descriptionToDisplay || 'No description for this character...'}
</div>
<div className="char__comics">Comics:</div>
<ul className="char__comics-list">
{comics.length
? comics.splice(0, 10).map(({ name, resourceURI }) => {
const comicId = resourceURI.split('/').at(-1);
return (
<li className="char__comics-item" key={comicId}>
<Link to={`/comic/${comicId}`}>{name}</Link>
</li>
);
})
: 'No comics found for this character'}
</ul>
</div>
)}
</Transition>
);
}
// Skeleton for loading
const CharacterInfoLoadingSkeleton = ({ initialTitle }) => {
const title = initialTitle ? (
<p
style={{
fontWeight: 'bold',
fontSize: '18px',
textAlign: 'center',
margin: '5px 0 10px',
}}
>
{initialTitle}
</p>
) : null;
return (
<>
{title}
<Skeleton variant="circular" width={80} height={80} animation="wave" />
<Skeleton
style={{ margin: '15px 0' }}
variant="rectangular"
height={150}
animation="wave"
/>
<Skeleton animation="wave" />
<Skeleton animation="wave" />
<Skeleton animation="wave" />
</>
);
};
// Main function component
const CharInfo = props => {
// State
const [chosenCharacter, setChosenCharacter] = useState(null);
const [initialTitle, setInitialTitle] = useState(
'Choose character from list on the left'
);
const { fetchSingleCharacter, loading, error } = useMarvelService();
// State managment
const onNewCharacterId = newCharacter =>
setChosenCharacter(() => newCharacter);
// Update character
const updateCharacterInfo = () => {
if (!props.characterId) {
return;
}
// Fetch clicked character, store it into state and stop loading
// also call onError function if error occures
return fetchSingleCharacter(props.characterId)
.then(response => {
setInitialTitle(null);
return onNewCharacterId(response);
})
.catch(e => {
throw e;
})
.finally();
};
// Updating character when component is mounted to display its info
// eslint-disable-next-line
useEffect(() => updateCharacterInfo, []);
// Updating character to display its info
useEffect(() => {
async function fetchData() {
return await updateCharacterInfo();
}
fetchData();
// eslint-disable-next-line
}, [props.characterId]);
const content =
!loading && !error && chosenCharacter ? (
<>
<BasicCharacterInfo data={chosenCharacter} />
</>
) : error ? (
<ErrorMessage />
) : (
<CharacterInfoLoadingSkeleton initialTitle={initialTitle} />
);
return <div className="char__info">{content}</div>;
};
export default CharInfo;
I am trying to add animations with react-transition-goup but its' behavior is not correct.

DraftJS blockstyle (header-one) not getting triggered

I have used draftJS in my project as a note taker. The inline styles are working perfectly fine but the blockType aren't.
Used the RichUtils to toggleInlineStyles and toggleBlockType.
Main DraftJS.jsx file :
class PageContainer extends React.Component {
constructor(props) {
super(props);
this.state = {
editorState: EditorState.createEmpty(),
alignment: "align-left",
};
this.setDomEditorRef = ref => (this.domEditor = ref);
this.focus = () => this.domEditor.focus();
this.onChange = editorState => {
this.setState({
...this.state,
editorState,
});
};
}
handleKeyCommand = command => {
const newState = RichUtils.handleKeyCommand(
this.state.editorState,
command,
);
if (newState) {
this.onChange(newState);
return "handled";
}
return "not-handled";
};
blockStyleFn = () => {
return this.state.alignment;
};
handleAlignment = alignment => {
this.setState({
...this.state,
alignment,
});
};
toggleInlineStyle = inlineStyle => {
this.onChange(
RichUtils.toggleInlineStyle(this.state.editorState, inlineStyle),
);
};
toggleBlockType = blockType => {
this.onChange(RichUtils.toggleBlockType(this.state.editorState, blockType));
};
render() {
return (
<div className="flex items-center justify-center h-screen ">
<div className="overflow-hidden shadow-md min-w-[422px] rounded-2xl ">
<div
onClick={this.focus}
className="editors min-h-[210px] break-words text-base p-6 bg-white border-b-[1px] border-primary-400">
<Editor
blockStyleFn={this.blockStyleFn}
className="text-secondary-400"
editorState={this.state.editorState}
handleKeyCommand={this.handleKeyCommand}
onChange={this.onChange}
placeholder="Take notes here..."
spellCheck={true}
ref={this.setDomEditorRef}
/>
</div>
<div className="flex justify-between py-4 px-6 ">
<div className="flex flex-1 justify-between">
<InlineStyleControls
editorState={this.state.editorState}
onToggleInLineStyle={this.toggleInlineStyle}
onToggleBlock={this.toggleBlockType}
focus={this.focus}
/>
</div>
<VerticalBorder className="mx-7" />
<AlignTextControls
handleAlignment={this.handleAlignment}
focus={this.focus}
currentAlignment={this.state.alignment}
/>
</div>
</div>
</div>
);
}
}
InLineStyleControls.jsx :
const InlineStyleControls = props => {
const INLINE_STYLES = [
{
label: "Bold",
style: "BOLD",
icon: bold => <BoldIcon bold={bold} />,
},
{
label: "Italic",
style: "ITALIC",
icon: bold => <ItalicIcon bold={bold} />,
},
{
label: "Underline",
style: "UNDERLINE",
icon: bold => <UnderlineIcon bold={bold} />,
},
{
label: "H1",
style: "header-one",
icon: bold => <TextIcon bold={bold} />,
},
];
let currentStyle = props.editorState.getCurrentInlineStyle();
const selection = props.editorState.getSelection();
const blockType = props.editorState
.getCurrentContent()
.getBlockForKey(selection.getStartKey())
.getType();
return (
<div className="flex flex-1 justify-between">
{INLINE_STYLES.map(type => (
<StyleButton
key={type.label}
active={
type.label === "H1"
? type.style === blockType
: currentStyle.has(type.style)
}
icon={type.icon}
onToggle={type.label === "H1" ? props.onToggleBlock : props.onToggleInLineStyle}
style={type.style}
focus={props.focus}
/>
))}
<span className="cursor-pointer">
<TextColor />
</span>
</div>
);
};
StyleButton.jsx:
class StyleButton extends React.Component {
constructor() {
super();
this.onToggle = e => {
e.preventDefault();
this.props.onToggle(this.props.style);
};
}
render() {
return (
<span className={` cursor-pointer ${this.props.class} `} onMouseDown={this.onToggle} onMouseUp={this.props.focus} >
{this.props.icon(this.props.active ? 2 : 1)}
</span>
);
}
}
Problem : Everything is working fine except the "header-one" and I not able to figure out why.
I used the rich editor example to build this.
Edit : I found the problem. The problem was due to tailwind css. When I remove tailwind from my project everything is working fine. any idea on to how to make draftJS work with tailwind?

React for table rows to bind (this) click event handler

I have a table rows data from server containing images (some other data is removed for simplicity). When images clicked, a modal popup is shown to preview the loaded image to crop and change the image with the cropped one. Everything is work fine.
The problem is, the clicked image on the row should change after the modal submit button is clicked. But I found that the image on the last row is changed.
I know the problem comes from this line but I have no idea how to solve it :
handleSubmit = e => {
e.preventDefault();
console.log(this.state.croppedImageUrl);
this.imagetoCropt.src = this.state.croppedImageUrl;
};
This is the code :
import React, { Component } from "react";
import { Link } from "react-router-dom";
import { Button } from "react-bootstrap";
import { Modal } from "react-bootstrap";
import ReactCrop from "react-image-crop";
import "react-image-crop/dist/ReactCrop.css";
import { my_ads } from "./component/AdsFunctions";
export default class Myads extends Component {
constructor() {
super();
this.state = {
myads : {},
modalShow: false,
setShow: false,
setClose: true,
previewImage: "/assets/loader.gif",
src: null,
crop: {
unit: "%",
width: 30,
aspect: 5 / 4
}
};
}
handleImageOnChange = e => {
if (e.target.files && e.target.files.length > 0) {
const reader = new FileReader();
reader.addEventListener("load", () =>
this.setState({
src: reader.result,
modalShow: true
})
);
reader.readAsDataURL(e.target.files[0]);
}
};
onImageLoaded = image => {
this.imageRef = image;
};
onCropComplete = crop => {
this.makeClientCrop(crop);
};
onCropChange = (crop, percentCrop) => {
this.setState({ crop });
};
async makeClientCrop(crop) {
if (this.imageRef && crop.width && crop.height) {
const croppedImageUrl = await this.getCroppedImg(
this.imageRef,
crop,
"newFile.jpeg"
);
this.setState({ croppedImageUrl });
}
}
getCroppedImg(image, crop, fileName) {
const canvas = document.createElement("canvas");
const scaleX = image.naturalWidth / image.width;
const scaleY = image.naturalHeight / image.height;
canvas.width = crop.width;
canvas.height = crop.height;
const ctx = canvas.getContext("2d");
ctx.drawImage(
image,
crop.x * scaleX,
crop.y * scaleY,
crop.width * scaleX,
crop.height * scaleY,
0,
0,
crop.width,
crop.height
);
return new Promise((resolve, reject) => {
canvas.toBlob(blob => {
if (!blob) {
//reject(new Error('Canvas is empty'));
console.error("Canvas is empty");
return;
}
blob.name = fileName;
window.URL.revokeObjectURL(this.fileUrl);
this.fileUrl = window.URL.createObjectURL(blob);
resolve(this.fileUrl);
}, "image/jpeg");
});
}
//---- modal function ------------
handleShow = () => {
this.setState({
modalShow: true
});
};
handleClose = () => {
this.setState({
modalShow: false
});
};
handleImgClick = () => {
this.refs.fileInput.click();
};
handleClickSubmit = () => {
this.refs.btnSubmit.click();
this.setState({
modalShow: false
});
};
//--------- end modal function---
//======== PROBLEM HERE ======================
handleSubmit = e => {
e.preventDefault();
console.log(this.state.croppedImageUrl);
this.imagetoCropt.src = this.state.croppedImageUrl;
};
//=============================================
componentDidMount() {
// AXIOS call
my_ads().then(res => {
this.setState({
myads: res.myads,
});
});
}
render() {
const { crop, croppedImageUrl, src } = this.state;
const show = this.state.modalShow;
// My Ads List from AXIOS call
let myads = this.state.myads;
const RenderMyAds = Object.keys(myads).map((val, index) => (
<tr className="mt-3" key={index}>
<td>
<div className="float-left mr-4">
<div className="card mb-10">
<Link to="#">
<img
className="img-thumbnail img-responsive"
src={myads[val].image}
alt="img"
width={200}
onClick={this.handleImgClick}
ref={ref => (this.imagetoCropt = ref)} <<==== problem here?
/>
</Link>
</div>
</div>
</td>
</tr>
));
return (
<div>
<section>
<div className="container">
<div className="row">
<div className="col-lg-12">
<div className="card">
<div className="card-body">
<div className="table-responsive">
<table className="table table-bordered border-top mb-0">
<tbody>
{RenderMyAds}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<form
encType="multipart/form-data"
acceptCharset="utf-8"
onSubmit={this.handleSubmit}
>
<input
type="file"
className="d-none"
name="userfile"
ref="fileInput"
onChange={this.handleImageOnChange}
/>
<button type="submit" className="d-none" ref="btnSubmit">
Upload Image
</button>
</form>
<Modal size="lg" show={show} onHide={this.handleClose}>
<Modal.Header closeButton>
<Modal.Title>Image Preview</Modal.Title>
</Modal.Header>
<Modal.Body className="text-center"></Modal.Body>
<ReactCrop
src={src}
crop={crop}
onImageLoaded={this.onImageLoaded}
onComplete={this.onCropComplete}
onChange={this.onCropChange}
/>
<img className="d-none" alt="Crop" src={croppedImageUrl} />
<Modal.Footer>
<Button
variant="primary"
className="btn-block"
onClick={this.handleClickSubmit}
>
<i className="fa fa-image mr-2"></i> Upload Image
</Button>
</Modal.Footer>
</Modal>
</div>
);
}
}
You are overwriting the same ref in your map. Consequentially, the last row is the last one to be mapped. You need to instead use an array of refs.
In your contructor, add:
this.imageRefs = [];
Then in your mapping:
const RenderMyAds = Object.keys(myads).map((val, index) => (
<tr className="mt-3" key={index}>
<td>
<div className="float-left mr-4">
<div className="card mb-10">
<Link to="#">
<img
className="img-thumbnail img-responsive"
src={myads[val].image}
alt="img"
width={200}
onClick={this.handleImgClick}
ref={ref => (this.imageRefs[index] = ref)}
/>
</Link>
</div>
</div>
</td>
</tr>
));
This will let you access the correct ref, based on the key assigned to the tr.

Disable Prev or Next Button if there is no slides available before or after the current slide in react slick. (PreviousNextMethod)

I used react slick PrevNextMethod
https://react-slick.neostack.com/docs/example/previous-next-methods
I set the Infinite to false so, there is no loop will shown in carousel.
Now, i want to disable the previous button if there is no slides available before the current showing slide or to disable next button vise versa..
There is no options in official documentation. is there anyway to achieve this?
Using custom arrows you can get the className property on custom arrow component, react-slick add the class slick-disabled to that arrow when it does not have more slide to show, so with that in mind you can check className?.includes("slick-disabled"), more details following:
import React from "react";
import Slider from "react-slick";
const NextArrow: React.FC<ArrowsProps> = ({ onClick, className }) => (
<ArrowRightContainer onClick={onClick} isDisabled={className?.includes("slick-disabled")}>
<Icon name="chevron-right" />
</ArrowRightContainer>
);
const PrevArrow: React.FC<ArrowsProps> = ({ onClick, className }) => (
<ArrowLeftContainer onClick={onClick} isDisabled={className?.includes("slick-disabled")}>
<Icon name="chevron-right" styles={ArrowLeftIcon} />
</ArrowLeftContainer>
);
const settings = {
infinite: false,
speed: 350,
slidesToShow: 4,
slidesToScroll: 1,
nextArrow: <NextArrow />,
prevArrow: <PrevArrow />,
};
<Slider {...settings}>
.....
</Slider>
Yes, it can be done using the beforeChange callback.
Here's a basic example that I created from one of the examples in the docs:
export default class SimpleSlider extends Component {
state = { index: 0 };
next = () => {
this.slider.slickNext();
};
previous = () => {
this.slider.slickPrev();
};
beforeChange = (prev, next) => {
this.setState({ index: next });
};
render() {
const settings = {
infinite: false,
speed: 500,
slidesToShow: 1,
slidesToScroll: 1,
arrows: true,
beforeChange: this.beforeChange
};
const index = this.state.index;
return (
<div>
<h2> Single Item</h2>
<Slider {...settings} ref={c => (this.slider = c)}>
<div>
<h3>1</h3>
</div>
<div>
<h3>2</h3>
</div>
<div>
<h3>3</h3>
</div>
<div>
<h3>4</h3>
</div>
<div>
<h3>5</h3>
</div>
<div>
<h3>6</h3>
</div>
</Slider>
<div style={{ textAlign: "center" }}>
<button
className="button"
disabled={index === 0}
onClick={this.previous}
>
Previous
</button>
<button className="button" disabled={index === 5} onClick={this.next}>
Next
</button>
</div>
</div>
);
}
}
You just have to keep track of the index by keeping it in state somewhere.
Basic codepen here

React Current Image in Image Gallery

Hello i have a litle problem with react-image-gallery.
In ImageGallery component i pass startIndex value like this.state.currentImage and this.state.currentImage depends on number photo with we are going to click.
When we click on photo for example number 4 this.state.currentImage is chaining on number 4 and its correct for me but in <imageGallery/> component startIndex doesn't work like i should. My modal always start on first image index[0].
import React, { Component } from "react";
import { Modal, ModalClose, ModalBody } from "react-modal-bootstrap";
import ImageGallery from "react-image-gallery";
import "./index.css";
export default class Images extends Component {
constructor(props) {
super(props);
var data = { title: "photos", images: [], ...props.data };
this.state = {
open: false,
showPlayButton: true,
showGalleryPlayButton: false,
showFullscreenButton: true,
showGalleryFullscreenButton: false,
currentImage: 0,
test: 0,
player: [],
data: data
};
console.log("Images: ", this.state.data);
this.openLightbox = this.openLightbox.bind(this);
this._renderImages = this._renderImages.bind(this);
this._onSlide = this._onSlide.bind(this);
this._onReady = this._onReady.bind(this);
}
state = {
isOpen: false
};
openModal = event => {
console.log(event.target);
this.setState({ isOpen: true });
};
openLightbox(index, event) {
// console.log('index',index);
event.preventDefault();
// this.setState({
// isOpen: true,
// currentImage: index
// });
this.setState(
prevState => {
return {
currentImage: index,
isOpen: true
};
},
() => {
console.log("currentImage", this.state.currentImage);
console.log("event", index);
}
);
}
hideModal = () => {
this.setState({ isOpen: false });
};
_renderImages(item) {
return (
<div className="images image-gallery-image">
<div className="images image-wrapper">
<h1>{this.state.currentImage}</h1>
<img src={item.img} alt="" className="images multimedia_image" />
<span className="images image-gallery-description">{item.desc}</span>
</div>
</div>
);
}
_onReady(event) {
const player = this.state.player;
player.push(event.target);
this.setState({
player: player
});
}
_onSlide() {
this.state.data.images.forEach(player => {});
}
handleImageLoad(event) {
console.log("Image loaded ", event.target);
}
render() {
var openLightbox = this.openLightbox;
var currentImage = this.state.currentImage;
const number = this.state.currentImage;
return (
<div className="images row">
<div className="images col-xs-12 col-sm-12 col-md-12 col-lg-12">
<div className="images title">{this.state.data.title}</div>
</div>
<div className="images col-xs-12 col-sm-12 col-md-12 col-lg-12">
<div className="images row">
{this.state.data.images.map((object, i) => {
let backgroundImage = {
backgroundImage: "url(" + object.thumbnail + ")",
top: 0,
right: 0,
left: 0,
bottom: 0,
position: "absolute",
flex: 1,
backgroundPosition: "center",
backgroundSize: "cover",
zIndex: 1
};
return (
<div
className="images item col-xs-4 col-sm-4 col-md-3 col-lg-3 images__single-item"
key={i}
>
<div
className="images multimedia_button"
onClick={e => this.openLightbox(i, e)}
>
<div style={backgroundImage} />
</div>
</div>
);
})}
</div>
</div>
<Modal isOpen={this.state.isOpen} onRequestHide={this.hideModal}>
<button
type="button"
className="images player_button_close"
onClick={this.hideModal}
>
X
</button>
<ModalBody>
<ImageGallery
items={this.state.data.images}
startIndex={this.state.currentImage}
slideInterval={2000}
showPlayButton={false}
showFullscreenButton={false}
onImageLoad={this.handleImageLoad}
onSlide={this._onSlide}
showIndex={true}
renderItem={this._renderImages}
/>
</ModalBody>
</Modal>
</div>
);
}
}
I found a solution when I needed to reinitialize current element. It can be useful for some other dev.
The answer is A “key” a special string attribute when we create lists of elements.
Whenever "key" is going change element is rerender. So
this.state = {
open: false,
showPlayButton: true,
showGalleryPlayButton: false,
showFullscreenButton: true,
showGalleryFullscreenButton: false,
currentImage: 0,
test: 0,
player: [],
data: data,
number:0
};
openLightbox(index, event) {
event.preventDefault();
this.setState(
prevState => {
return {
currentImage: index,
isOpen: true,
number:prevState.number+1
};
},
() => {
console.log("currentImage", this.state.currentImage);
console.log("event", index);
}
);
And here we neet to add our key={this.state.number}
<Modal isOpen={this.state.isOpen} onRequestHide={this.hideModal}>
<button
type="button"
className="images player_button_close"
onClick={this.hideModal}
>
X
</button>
<ModalBody>
<ImageGallery
key={this.state.number}
items={this.state.data.images}
startIndex={this.state.currentImage}
slideInterval={2000}
showPlayButton={false}
showFullscreenButton={false}
onImageLoad={this.handleImageLoad}
onSlide={this._onSlide}
showIndex={true}
renderItem={this._renderImages}
/>
</ModalBody>
</Modal>

Resources