Creé un menú de arrastrar y soltar y hasta ahora todo funciona, sin embargo, me encontré con un pequeño problema de codificación para mi último paso. Necesito que el menú de elementos se desplace automáticamente cuando el elemento arrastrado esté hacia la parte inferior del contenedor (o superior). Decidí estructurarlo de modo que cuando el cursor que arrastra el elemento cae por debajo de un rango específico hacia la parte inferior, se activará una función de desplazamiento y se desplazará continuamente hacia abajo a un ritmo que puedo configurar. Para lograr esto, configuré una función setInterval y llamaré continuamente a una función scrollBy.
Mi problema es que para detener setInterval y llamar a clearInterval, necesito saber cuándo la posición del cursor ya no está en ese rango. Cada vez que se llama a la función en setInterval, toma una instantánea de las variables de estado actuales. En lugar de actualizar el estado de esas variables (posición del eje y) dentro de la función, se atasca en el primer valor que obtiene.
El yPoisiton se obtiene con el window.event.clientY de otro componente.
document.onmousemove = (e) => { if (dragging.state) { var newYPos = window.event.clientY; setYPos(newYPos); handleScroll(newYPos, dragging.state);El resto del código es el siguiente:
const menuContainer = useRef(); const [scrolling, setScrolling] = useState(false); const [yPos, setYPos] = useState(null); const [dragging, setDragging] = useState({ state: false, index: null, y: null, height: null, }); function continueScrolling() { console.log("continueScrolling function"); console.log(yPos); // Same value even after updating via setYPos) const date = new Date(); console.log(date.toLocaleTimeString()); //Different values in accordance to the time } console.log("Index.js yPos"); console.log(yPos); // Different values every render when dragging const handleScroll = (draggingYPos, isDragging) => { // This is triggered onMouseMove in another component if ( draggingYPos > menuContainer.current.getBoundingClientRect().bottom - 100 && isDragging ) { setScrolling(true); // On the first cycle scrolling == false and executes the setInterval function. Each subsequent call is then skipped. if (scrolling) { return; } else { var intr = setInterval(function () { continueScrolling(); // Different method of testing and trying to get the current yPos in the function //Commented but shows a bit of what I'm trying to accomplish // if ( // !( // yPos > // menuContainer.current.getBoundingClientRect().bottom - 100 && // dragging.state // ) // ) // clearInterval(intr); }, 1000);Por favor, hágame saber si hay más información que necesita o cualquier otra cosa que pueda aclarar.
Esta es una solución temporal que encontré para mi problema, sin embargo, aún me gustaría conocer una solución más adecuada y robusta si alguien tiene una, así como información sobre el alcance de las funciones, el estado de React y cómo pasarlos entre unos y otros.
Me doy cuenta de que no se recomienda mutar estados directamente, sin embargo, esta es mi única solución de trabajo actual. Si creo un valor temporal y paso setInterval, llamará a setInterval por segunda vez y seguirá activo después de borrarlo.
Si declaro una variable const global, no puedo reasignar la variable con setInterval. Cuando declaré una variable global con var, la función setInterval continuó incluso después de que la borré.
Código ajustado:
const [scroll, setScroll] = useState(null); const handleScroll = (draggingYPos, isDragging) => { if ( draggingYPos > menuContainer.current.getBoundingClientRect().bottom - 100 && isDragging ) { setScrolling(true); if (scrolling) { return; } else { var count = 0; if ( !( yPos > menuContainer.current.getBoundingClientRect().bottom - 100 && dragging.state ) ) { setScroll( setInterval(function () { count += 1; console.log(count); }, 1000) ); } } } else { console.log("Not Scrolling"); setScroll(clearInterval(scroll)); setScrolling(false); } };