Il semble que useEffect soit déclenché même si l'état de dépendance n'a pas changé ?
P粉946336138
2023-08-15 16:21:30
<p>J'essaie de créer un composant carrousel dans mon projet React - j'essaie en fait d'exploiter un composant carrousel existant écrit en pur JS, en utilisant Refs pour le faire fonctionner dans React, plutôt que de le modifier directement DOM. Je rencontre un problème lorsque j'essaie d'initialiser le carrousel en marquant la première diapositive de la séquence comme diapositive actuelle (avec className current-slide). J'ai mis cette action dans un hook useEffect où {topMovies} est une dépendance. {topMovies} est un tableau d'objets transmis au composant carrousel via prop, donc lorsque topMovies change (c'est-à-dire se charge), useEffect doit s'exécuter. Cela fonctionne - après le chargement, la première diapositive du carrousel reçoit le nom de classe « diapositive actuelle ». </p>
<p>Cependant, le deuxième morceau de code (nextSlide et moveToSlide) est le début de la fonction qui sélectionne la diapositive suivante. Transmettez la référence de piste (c'est-à-dire le conteneur de toutes les diapositives) à la fonction afin que l'élément enfant avec le nom de classe 'current-slide' puisse être sélectionné et son nom de classe supprimé. Cela fonctionne également - mais après un court délai (~ 1 seconde), le nom de classe 'current-slide' réapparaît.</p>
<pre class="brush:php;toolbar:false;">const Carouselv2 = ({topMovies}) => {
//Réfs
const trackRef = useRef();
const nextBtnRef = useRef();
const prevBtnRef = useRef();
const navDotsRef = useRef();
//Initialiser le carrousel lors du chargement de l'hélice
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
if (topMovies && setIsLoading) {
const slides = Array.from(trackRef.current.children);
slides[0].classList.add('current-slide'); //Marquer la première diapositive comme visible
const slideWidth = slides[0].getBoundingClientRect().width;
const setSlidePosition = (diapositive, index) => {
slide.style.left = slideWidth * index + 'px';
}
slides.forEach(setSlidePosition); // Disposer les diapositives les unes à côté des autres
setIsLoading(faux);
}
}, [meilleurs films]);
//Fonctionnalité des boutons
const moveToSlide = (currentSlide, targetSlide) => {
//trackRef.current.style.transform = 'translateX(-' + targetSlide.style.left + ')';
currentSlide.classList.remove('current-slide');
//targetSlide.classList.add('current-slide');
}
const updateDots = () => {
}
const responsiveBtns = () => {
}
const prevSlide = (e) => {
}
const nextSlide = (e) => {
const currentSlide = trackRef.current.querySelector('.current-slide');
const nextSlide = trackRef.current.children.nextElementSibling;
moveToSlide(currentSlide, nextSlide);
}
retour (
<div className="carrousel">
<button className="carousel_button carousel_button--left" ref={prevBtnRef}><FontAwesomeIcon icon={faCircleLeft} size="xl" style={{ color: "white" }} /></button> ;
<div className="carousel_track-container">
<ul className="carousel_track" ref={trackRef}>
{topFilms && topMovies.map((film) => (
<li className="carousel_slide">
<img src={movie.image} alt="" />
<h2>{movie.title}</h2>
≪/li>
))}
</ul>
</div>
<button onClick={(e) => nextSlide(e)}className="carousel_button carousel_button--right" ref={nextBtnRef}><FontAwesomeIcon icon={faCircleRight} size="xl" style={{ couleur : "blanc" }} /></bouton>
<div className="carousel_nav" ref={navDotsRef}>
<button className="carousel_indicator current-slide"></button>
{topMovies && Array.apply(0, Array(topMovies.length)).map(() => {
return <button className="carousel_indicator"></button>
})}
</div>
</div>
);
}</pré>
<p>Ma pensée initiale était que, pour une raison quelconque, la modification de className provoquait le déclenchement de useEffect, j'ai donc ajouté une instruction if avec une condition isLoading. Mais cela n'a pas fonctionné, donc je ne pense pas que le bug vienne du hook useEffect. </p>
<p>Très confus par cela, mais c'est la première fois que j'utilise Refs, il est donc tout à fait possible que je manque quelque chose de très évident. Merci pour votre aide! </p>
Vous mélangez du DOM créé à l'aide de React et du DOM manipulé à l'aide de Javascript pur. Vous ne pouvez pas faire cela, cela romprait simplement la relation DOM/VDOM.
Si vous souhaitez éviter de déplacer l'ensemble du composant pour qu'il fonctionne comme le fait React, utilisez simplement Ref sur un élément vide, l'avantage est que vous bénéficiez des avantages du montage et du démontage des composants.
Ensuite, vous pouvez copier-coller le code Javascript et simplement tout mettre à l'intérieur
useEffect
.Par exemple :
Ci-dessous, j'ai créé deux boutons, l'un entièrement contrôlé par React et l'autre par JS, qui feront simplement basculer la classe
pink-button
lorsque vous cliquerez dessus. J'ai également placé une case à cocher pour inverser l'ordre des boutons afin de provoquer un nouveau rendu montrant que l'état de la version JS n'a pas été détruit, assurez-vous d'utiliser l'attributkey
lors de cette opération pour faire savoir à React qu'il s'agit du même composant. L'essentiel ici est de montrer que React n'interférera désormais plus avec ce bouton, c'est désormais entièrement votre responsabilité. J'espère que cela vous aidera à comprendre comment mélanger React avec du JS pur.