종속성 상태가 변경되지 않았는데도 useEffect가 트리거되는 것 같나요?
P粉946336138
2023-08-15 16:21:30
<p>저는 React 프로젝트에서 캐러셀 컴포넌트를 구축하려고 합니다. 실제로 DOM을 직접 수정하는 대신 Refs를 사용하여 순수 JS로 작성된 기존 캐러셀 컴포넌트를 활용하려고 합니다. 시퀀스의 첫 번째 슬라이드를 현재 슬라이드(className current-slide 사용)로 표시하여 회전식 슬라이드를 초기화하려고 하면 문제가 발생합니다. 이 작업을 {topMovies}가 종속성인 useEffect 후크에 넣었습니다. {topMovies}는 prop을 통해 캐러셀 구성요소에 전달되는 객체 배열이므로 topMovies가 변경되면(예: 로드) useEffect가 실행되어야 합니다. 이것은 작동합니다. 로딩 후 캐러셀의 첫 번째 슬라이드에는 클래스 이름 'current-slide'가 지정됩니다. </p>
<p>그러나 두 번째 코드 부분(nextSlide 및 moveToSlide)은 다음 슬라이드를 선택하는 함수의 시작 부분입니다. className이 'current-slide'인 하위 요소를 선택하고 해당 className을 제거할 수 있도록 트랙 Ref(즉, 모든 슬라이드의 컨테이너)를 함수에 전달합니다. 이 방법도 작동하지만 짧은 지연(~1초) 후에 className 'current-slide'가 다시 나타납니다.</p>
<pre class="brush:php;toolbar:false;">const Carouselv2 = ({topMovies}) => {
//참조
const trackRef = useRef();
const nextBtnRef = useRef();
const prevBtnRef = useRef();
const navDotsRef = useRef();
//소품 로드 시 캐러셀 초기화
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
if (topMovies && setIsLoading) {
const 슬라이드 = Array.from(trackRef.current.children);
Slides[0].classList.add('current-slide'); //첫 번째 슬라이드를 표시되도록 표시
const SlideWidth = 슬라이드[0].getBoundingClientRect().width;
const setSlidePosition = (슬라이드, 인덱스) => {
Slide.style.left = SlideWidth * 인덱스 + 'px';
}
Slides.forEach(setSlidePosition); //슬라이드를 서로 나란히 정렬
setIsLoading(false);
}
}, [topMovies]);
//버튼 기능
const moveToSlide = (currentSlide, targetSlide) => {
//trackRef.current.style.transform = 'translateX(-' + targetSlide.style.left + ')';
currentSlide.classList.remove('현재-슬라이드');
//targetSlide.classList.add('현재-슬라이드');
}
const updateDots = () => {
}
const ResponseBtns = () => {
}
const prevSlide = (e) => {
}
const nextSlide = (e) => {
const currentSlide = trackRef.current.querySelector('.current-slide');
const nextSlide = trackRef.current.children.nextElementSibling;
moveToSlide(currentSlide, nextSlide);
}
반품 (
<div className="carousel">
<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}>
{topMovies && topMovies.map((영화) => (
<li className="carousel_slide">
<img src={movie.image} alt="" />
<h2>{영화.제목}</h2>
</li>
))}
</ul>
</div>
<button onClick={(e) => nextSlide(e)}className="carousel_button carousel_button--right" ref={nextBtnRef}><FontAwesomeIcon icon={faCircleRight} size="xl" style={{ 색상: "흰색" }} /></button>
<div className="carousel_nav" ref={navDotsRef}>
<button className="carousel_indicator current-slide"></button>
{topMovies && Array.apply(0, Array(topMovies.length)).map(() => {
반환 <button className="carousel_indicator"></button>
})}
</div>
</div>
);
}</pre>
<p>처음에는 어떤 이유로 className을 변경하면 useEffect가 실행될 것이라고 생각하여 isLoading 조건이 있는 if 문을 추가했습니다. 그러나 그것은 작동하지 않았으므로 버그가 useEffect 후크에서 비롯된 것이라고 생각하지 않습니다. </p>
<p>이 점 때문에 매우 혼란스럽습니다. 하지만 Refs를 처음 사용하는 것이므로 아주 분명한 것을 놓치고 있을 가능성이 충분히 있습니다. 도와주셔서 감사합니다! </p>
React를 사용하여 만든 DOM과 순수 Javascript를 사용하여 조작한 DOM을 혼합하고 있습니다. 이렇게 하면 DOM/VDOM 관계가 깨질 뿐입니다.
React처럼 작동하도록 전체 구성 요소를 이동하지 않으려면 빈 요소에 Ref를 사용하면 구성 요소 마운트 및 마운트 해제의 이점을 얻을 수 있다는 이점이 있습니다.
그런 다음 Javascript 코드를 복사하여 붙여넣고 모두 안에 넣을 수 있습니다
useEffect
.예:
아래에는 두 개의 버튼을 만들었습니다. 하나는 React로 완전히 제어되고 다른 하나는 JS로 제어되며, 클릭하면
pink-button
클래스가 토글됩니다. 또한 JS 버전의 상태가 파괴되지 않았음을 다시 렌더링하도록 버튼 순서를 뒤집는 확인란을 배치했습니다. 이 작업을 수행할 때key
속성을 사용하여 React가 동일한 구성 요소임을 알 수 있도록 하세요. 여기서 중요한 점은 이제 React가 더 이상 이 버튼을 방해하지 않으며 이는 전적으로 귀하의 책임임을 보여주는 것입니다. 이것이 React와 순수 JS를 혼합하는 방법을 이해하는 데 도움이 되기를 바랍니다.