Saltar al contenido

¿Usando document.querySelector en React? ¿Debería usar refs en su lugar? ¿Cómo?

Nuestro equipo especializado luego de ciertos días de investigación y de recopilar de datos, dimos con los datos necesarios, nuestro deseo es que resulte útil para ti en tu plan.

Solución:

No puedo responder a la parte del “deberías” de si usar referencias para esto en lugar de si lo haces, no las necesitas. id valores a menos que los use para otra cosa.

Pero así es como lo harías:

  1. Usar useRef(null) para crear la ref.

    const activeSlideRef = useRef(null);
    
  2. Ponlo en el Slide que está actualmente activo

    
    
  3. En tus useEffect, usa las referencias current propiedad

    useEffect(() => 
        if (activeSlideRef.current) 
            activeSlideRef.current.scrollIntoView(
              behavior: 'smooth',
              block: 'nearest',
              inline: 'nearest'
            );
        
    , [activeSlide]);
    

    (Creo activeSlide es una dependencia razonable para ese efecto. No puede usar la referencia, la referencia en sí no varía …)

Ejemplo en vivo, he convertido algunos de sus componentes en divs por conveniencia:

const useEffect, useRef, useState = React;

function Deck(children) 
    const [activeSlide, setActiveSlide] = useState(0);
    const activeSlideRef = useRef(null);

    useEffect(() => 
        if (activeSlideRef.current) 
            activeSlideRef.current.scrollIntoView(
              behavior: 'smooth',
              block: 'nearest',
              inline: 'nearest'
            );
        
    , [activeSlide]);

    const moveLeft = Math.max(0, activeSlide - 1);
    const moveRight = Math.min(children.length - 1, activeSlide + 1);

    return (
        
          
          
children.map((child, i) => const active = i === activeSlide; return (
child
); )
); ReactDOM.render(
slide 0
slide 1
slide 2
slide 3
slide 4
slide 5
slide 6
slide 7
slide 8
slide 9
, document.getElementById("root") );
.slide 
  height: 4em;
  vertical-align: middle;
  text-align: center;

#test 
  overflow: scroll;
  max-height: 20em;

.active 
  font-weight: bold;
  color: blue;


En un comentario has preguntado:

¿Sabe si es posible deshabilitar useEffect aquí para el primer render?

Para mantener información no estatal por componente, es interesante que utilice useRef. Los documentos para useRef señale que no es solo para referencias de elementos DOM, también es para datos no estatales por componente. Para que pudieras tener

const firstRenderRef = useRef(true);

entonces en tu useEffect devolución de llamada, comprobar firstRenderRef.current & mndash; si es true, configurarlo false, de lo contrario, haz el desplazamiento:

const useEffect, useRef, useState = React;

function Deck(children) 
    const [activeSlide, setActiveSlide] = useState(0);
    const activeSlideRef = useRef(null);
    // *** Use a ref with the initial value `true`
    const firstRenderRef = useRef(true);

    console.log("render");

    useEffect(() => 
        // *** After render, don't do anything, just remember we've seen the render
        if (firstRenderRef.current) 
            console.log("set false");
            firstRenderRef.current = false;
         else if (activeSlideRef.current) 
            console.log("scroll");
            activeSlideRef.current.scrollIntoView(
              behavior: 'smooth',
              block: 'nearest',
              inline: 'nearest'
            );
        
    , [activeSlide]);

    const moveLeft = Math.max(0, activeSlide - 1);
    const moveRight = Math.min(children.length - 1, activeSlide + 1);

    return (
        
          
          
children.map((child, i) => const active = i === activeSlide; return (
child
); )
); ReactDOM.render(
slide 0
slide 1
slide 2
slide 3
slide 4
slide 5
slide 6
slide 7
slide 8
slide 9
, document.getElementById("root") );
.slide 
  height: 4em;
  vertical-align: middle;
  text-align: center;

#test 
  overflow: scroll;
  max-height: 10em;

.active 
  font-weight: bold;
  color: blue;


Como experimento mental, escribí un gancho para facilitar un poco la ergonomía:

function useInstance(instance = ) 
    // assertion: instance && typeof instance === "object"
    const ref = useRef(instance);
    return ref.current;

Uso:

const inst = useInstance(first: true);

En useEffect, si inst.first es true, hacer inst.first = false;; de lo contrario, realice el desplazamiento.

Vivir:

const useEffect, useRef, useState = React;

function useInstance(instance = ) 
    // assertion: instance && typeof instance === "object"
    const ref = useRef(instance);
    return ref.current;


function Deck(children) 
    const [activeSlide, setActiveSlide] = useState(0);
    const activeSlideRef = useRef(null);
    const inst = useInstance(first: true);

    console.log("render");

    useEffect(() => 
        // *** After render, don't do anything, just remember we've seen the render
        if (inst.first) 
            console.log("set false");
            inst.first = false;
         else if (activeSlideRef.current) 
            console.log("scroll");
            activeSlideRef.current.scrollIntoView(
              behavior: 'smooth',
              block: 'nearest',
              inline: 'nearest'
            );
        
    , [activeSlide]);

    const moveLeft = Math.max(0, activeSlide - 1);
    const moveRight = Math.min(children.length - 1, activeSlide + 1);

    return (
        
          
          
children.map((child, i) => const active = i === activeSlide; return (
child
); )
); ReactDOM.render(
slide 0
slide 1
slide 2
slide 3
slide 4
slide 5
slide 6
slide 7
slide 8
slide 9
, document.getElementById("root") );
.slide 
  height: 4em;
  vertical-align: middle;
  text-align: center;

#test 
  overflow: scroll;
  max-height: 10em;

.active 
  font-weight: bold;
  color: blue;

Sección de Reseñas y Valoraciones

Tienes la opción de respaldar nuestra función fijando un comentario o dejando una puntuación te lo agradecemos.

¡Haz clic para puntuar esta entrada!
(Votos: 2 Promedio: 4.5)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *