Rumah  >  Soal Jawab  >  teks badan

Nampaknya useEffect dicetuskan walaupun keadaan kebergantungan tidak berubah?

<p>Saya cuba membina komponen karusel dalam projek React saya - Saya sebenarnya cuba memanfaatkan komponen karusel sedia ada yang ditulis dalam JS tulen, menggunakan Refs untuk menjadikannya berfungsi dalam React, dan bukannya mengubah suai terus DOM. Saya menghadapi masalah apabila saya cuba memulakan karusel dengan menandakan slaid pertama dalam jujukan sebagai slaid semasa (dengan slaid semasa className). Saya meletakkan tindakan ini dalam cangkuk useEffect di mana {topMovies} adalah kebergantungan. {topMovies} ialah tatasusunan objek yang dihantar ke komponen karusel melalui prop, jadi apabila topMovies berubah (iaitu dimuatkan), useEffect harus dijalankan. Ini berfungsi - selepas memuatkan, slaid pertama dalam karusel diberi nama kelas 'slaid semasa'. </p> <p>Walau bagaimanapun, sekeping kod kedua (nextSlide dan moveToSlide) ialah permulaan fungsi yang memilih slaid seterusnya. Hantar Rujukan trek (iaitu bekas semua slaid) ke fungsi supaya elemen anak dengan className 'current-slide' boleh dipilih dan classNamenya dialih keluar. Ini juga berfungsi - tetapi selepas kelewatan yang singkat (~1 saat) className 'current-slide' muncul semula.</p> <pre class="brush:php;toolbar:false;">const Carouselv2 = ({topMovies}) => { //Ruj const trackRef = useRef(); const nextBtnRef = useRef(); const prevBtnRef = useRef(); const navDotsRef = useRef(); //Memulakan karusel apabila beban prop const [isLoading, setIsLoading] = useState(true); useEffect(() => { if (Filem && setIsLoading teratas) { slaid const = Array.from(trackRef.current.children); slaid[0].classList.add('slaid semasa'); //Tandakan slaid pertama sebagai boleh dilihat const slideWidth = slaid[0].getBoundingClientRect().width; const setSlidePosition = (slaid, indeks) => { slide.style.left = slideWidth * indeks + 'px'; } slides.forEach(setSlidePosition); //Susun slaid bersebelahan antara satu sama lain setIsLoading(false); } }, [Filem teratas]); //Kefungsian butang const moveToSlide = (currentSlide, targetSlide) => { //trackRef.current.style.transform = 'translateX(-' + targetSlide.style.left + ')'; currentSlide.classList.remove('current-slide'); //targetSlide.classList.add('current-slide'); } kemas kini constDots = () => { } const responsifBtns = () => { } const prevSlide = (e) => { } const nextSlide = (e) => { const currentSlide = trackRef.current.querySelector('.current-slide'); const nextSlide = trackRef.current.children.nextElementSibling; moveToSlide(currentSlide, nextSlide); } kembali ( <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((filem) => ( <li className="carousel_slide"> <img src={movie.image} alt="" /> <h2>{movie.title}</h2> </li> ))} </ul> </div> <butang onClick={(e) => nextSlide(e)}className="carousel_button carousel_button--right" ref={nextBtnRef}><FontAwesomeIcon icon={faCircleRight} size="xl" style={{ warna: "putih" }} /></button> <div className="carousel_nav" ref={navDotsRef}> <button className="carousel_indicator current-slide"></button> {topMovies && Array.apply(0, Array(topMovies.length)).map(() => { kembalikan <button className="carousel_indicator"></button> })} </div> </div> ); }</pre> <p>Pemikiran awal saya ialah atas sebab tertentu, menukar className menyebabkan useEffect terbakar, jadi saya menambah pernyataan if dengan keadaan isLoading. Tetapi itu tidak berjaya, jadi saya tidak fikir pepijat itu datang daripada cangkuk useEffect. </p> <p>Sangat keliru dengan ini, tetapi ini kali pertama saya menggunakan Rujukan, jadi kemungkinan besar saya kehilangan sesuatu yang sangat jelas. Terima kasih atas bantuan anda! </p>
P粉946336138P粉946336138403 hari yang lalu476

membalas semua(1)saya akan balas

  • P粉642436282

    P粉6424362822023-08-16 10:19:47

    Anda sedang mencampurkan DOM yang dibuat menggunakan React dan DOM yang dimanipulasi menggunakan Javascript tulen. Anda tidak boleh melakukan ini, ia hanya akan memutuskan hubungan DOM/VDOM.

    Jika anda ingin mengelak daripada menggerakkan keseluruhan komponen untuk berfungsi seperti yang dilakukan oleh React, maka hanya gunakan Ref pada elemen kosong, faedahnya ialah anda mendapat faedah pemasangan dan nyahlekap komponen.

    Kemudian anda boleh salin-tampal kod Javascript dan letakkan semuanya di dalam useEffect.

    Contohnya:

    Di bawah saya telah mencipta dua butang, satu dikawal sepenuhnya oleh React dan satu lagi oleh JS, yang hanya akan menogol kelas pink-button apabila anda mengklik padanya. Saya juga meletakkan kotak pilihan untuk membalikkan susunan butang untuk menyebabkan pemaparan semula menunjukkan bahawa keadaan versi JS tidak dimusnahkan, pastikan anda menggunakan atribut key semasa melakukan ini untuk memberitahu React bahawa ia adalah komponen yang sama. Perkara utama di sini adalah untuk menunjukkan bahawa React kini tidak lagi mengganggu butang ini, ia kini menjadi tanggungjawab anda sepenuhnya. Harap ini membantu anda memahami cara mencampurkan React dengan JS tulen.

    const domContainer = document.querySelector('#mount');
    const root = ReactDOM.createRoot(domContainer);
    
    const {createRef, useEffect, useState} = React;
    
    function JSButton() {
      const btnRef = createRef(); 
      useEffect(() => {
         //do everything now from inside this useEffect
         const btn = btnRef.current;     
         btn.innerText = 'This is a Javascript Button';     
         const doClick = () => btn.classList.toggle('pink-button');
         btn.addEventListener('click', doClick);     
         return () => {
           //we can also do any clean-up here
           btn.removeEventListner('click', doClick);
         }
      }, []);
      //only render the button component,
      //don't add any props, classes etc.
      //our JS will be handling it all.
      return <button ref={btnRef}/>;
    }
    
    function ReactButton() {
      const [pink, setPink] = useState(false);
      return <button 
        onClick={() => setPink(p => !p)}
        className={pink ? 'pink-button' : ''}>
        React Button
      </button>;
    }
    
    function Test() {
      const [jsFirst, setJsFirst] = useState(false);
      return <React.Fragment>
         <input type="checkbox"
           checked={jsFirst}
           onChange={(e) => {
             setJsFirst(e.target.checked);
           }}
         />Js First
         {jsFirst 
           ? <React.Fragment>
               <JSButton key={'js'}/>
               <ReactButton key={'r'}/>
             </React.Fragment>
           : <React.Fragment>
               <ReactButton key={'r'}/>
               <JSButton key={'js'}/>
             </React.Fragment>       
         }
      </React.Fragment>
    }
    
    root.render(<Test/>);
    .pink-button {
      background-color: pink;
    }
    
    button {
      display: block;
      width: 200px;
      margin: 1rem;
    }
    <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    
    <div id="mount"></div>

    balas
    0
  • Batalbalas