He creado un componente en React que se supone que actualiza su propio estilo en el desplazamiento de la ventana para crear un efecto de paralaje.
El render
método del componente se ve así:
function() {
let style = { transform: 'translateY(0px)' };
window.addEventListener('scroll', (event) => {
let scrollTop = event.srcElement.body.scrollTop,
itemTranslate = Math.min(0, scrollTop/3 - 60);
style.transform = 'translateY(' + itemTranslate + 'px)');
});
return (
<div style={style}></div>
);
}
Esto no funciona porque React no sabe que el componente ha cambiado y, por lo tanto, el componente no se vuelve a procesar.
He intentado almacenar el valor de itemTranslate
en el estado del componente y llamar setState
a la devolución de llamada de desplazamiento. Sin embargo, esto hace que el desplazamiento sea inutilizable ya que es terriblemente lento.
¿Alguna sugerencia sobre cómo hacer esto?
javascript
reactjs
Alejandro Pérez
fuente
fuente
render
en el mismo hilo) solo deben ocuparse de la lógica relacionada con la representación / actualización del DOM real en React. En cambio, como se muestra a continuación en @AustinGreco, debe usar los métodos de ciclo de vida React para crear y eliminar el enlace de su evento. Esto lo hace autónomo dentro del componente y asegura que no haya fugas al asegurarse de que se elimine el enlace del evento si / cuando el componente que lo usa está desmontado.Respuestas:
Deberías vincular al oyente en
componentDidMount
, de esa manera solo se crea una vez. Debería poder almacenar el estilo en estado, el oyente probablemente fue la causa de los problemas de rendimiento.Algo como esto:
fuente
this.handleScroll = this.handleScroll.bind(this)
lo vincularáhandleScroll
al componente, en lugar de a la ventana.event.target.scrollingElement.scrollTop
Puede pasar una función al
onScroll
evento en el elemento React: https://facebook.github.io/react/docs/events.html#ui-eventsOtra respuesta que es similar: https://stackoverflow.com/a/36207913/1255973
fuente
Mi solución para hacer una barra de navegación receptiva (posición: 'relativa' cuando no se desplaza y fija cuando se desplaza y no en la parte superior de la página)
No hay problemas de rendimiento para mí.
fuente
Para ayudar a cualquier persona que haya notado los problemas de comportamiento / rendimiento lentos cuando usa la respuesta de Austins, y quiere un ejemplo usando las referencias mencionadas en los comentarios, aquí hay un ejemplo que estaba usando para alternar una clase para un icono de desplazamiento hacia arriba / abajo:
En el método de renderizado:
En el método del controlador:
Y agregue / elimine sus controladores de la misma manera que Austin mencionó:
documentos en las referencias .
fuente
this.scrollIcon.className = whatever-you-want
.className
oclassList
. Además, no necesitabawindow.addEventListener()
: ¡solo usé React'sonScroll
, y es tan rápido, siempre y cuando no actualices accesorios / estado!Descubrí que no puedo agregar con éxito el detector de eventos a menos que pase true de la siguiente manera:
fuente
userCapture
: Opcional. Un valor booleano que especifica si el evento debe ejecutarse en la captura o en la fase de burbujeo. Valores posibles: verdadero: el controlador de eventos se ejecuta en la fase de captura falso: predeterminado. El controlador de eventos se ejecuta en la fase de burbujeoUn ejemplo usando classNames , React hooks useEffect , useState y styled-jsx :
fuente
con ganchos
fuente
Ejemplo de componente de función usando useEffect:
Nota : Debe eliminar el detector de eventos devolviendo una función de "limpieza" en useEffect. Si no lo hace, cada vez que el componente se actualice tendrá un detector de desplazamiento de ventana adicional.
fuente
Si lo que le interesa es un componente secundario que se desplaza, entonces este ejemplo podría ser útil: https://codepen.io/JohnReynolds57/pen/NLNOyO?editors=0011
fuente
Resolví el problema usando y modificando variables CSS. De esta manera, no tengo que modificar el estado del componente que causa problemas de rendimiento.
index.css
Navbar.jsx
Navbar.module.css
fuente
Mi apuesta aquí es usar componentes de función con nuevos ganchos para resolverlo, pero en lugar de usar
useEffect
como en respuestas anteriores, creo que la opción correcta seríauseLayoutEffect
por una razón importante:Esto se puede encontrar en la documentación de React . Si usamos en su
useEffect
lugar y volvemos a cargar la página ya desplazada, el desplazamiento será falso y nuestra clase no se aplicará, causando un comportamiento no deseado.Un ejemplo:
Una posible solución al problema podría ser https://codepen.io/dcalderon/pen/mdJzOYq
fuente
useLayoutEffect
. Estoy tratando de ver lo que has mencionado.useEffect
aquí en comparación conuseLayoutEffect
..Header--scrolled
veces aplica la clase, pero un 100% de las veces.Header--scrolledLayout
se aplica correctamente gracias a useLayoutEffect.Aquí hay otro ejemplo usando HOOKS fontAwesomeIcon y Kendo UI React
[! [Captura de pantalla aquí] [1]] [1]
fuente
Actualización para una respuesta con React Hooks
Estos son dos ganchos: uno para la dirección (arriba / abajo / ninguno) y otro para la posición real
Usar así:
Aquí están los ganchos:
fuente
Para ampliar la respuesta de @ Austin, debe agregar
this.handleScroll = this.handleScroll.bind(this)
a su constructor:Esto da
handleScroll()
acceso al ámbito adecuado cuando se llama desde el detector de eventos.También tenga en cuenta que no puede hacer el
.bind(this)
de lasaddEventListener
oremoveEventListener
los métodos, ya que se no se eliminarán cada devuelven Referencias a diferentes funciones y el evento cuando los desmontajes de componentes.fuente