Eu construí um componente no React que deveria atualizar seu próprio estilo no scroll da janela para criar um efeito de paralaxe.
O render
método component se parece com o seguinte:
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>
);
}
Isso não funciona porque o React não sabe que o componente foi alterado e, portanto, o componente não é renderizado novamente.
Tentei armazenar o valor itemTranslate
no estado do componente e chamar setState
o retorno de chamada de rolagem. No entanto, isso torna a rolagem inutilizável, pois é muito lenta.
Alguma sugestão de como fazer isso?
javascript
reactjs
Alejandro Pérez
fonte
fonte
render
no mesmo encadeamento) devem se preocupar apenas com a lógica referente à renderização / atualização do DOM real no React. Em vez disso, como mostrado por @AustinGreco abaixo, você deve usar os métodos de ciclo de vida React fornecidos para criar e remover sua ligação de evento. Isso o torna independente dentro do componente e garante que não haja vazamentos, certificando-se de que a ligação do evento seja removida se / quando o componente que o usa estiver desmontado.Respostas:
Você deve ligar o ouvinte
componentDidMount
, para que ele seja criado apenas uma vez. Você deve poder armazenar o estilo no estado, provavelmente o ouvinte foi a causa dos problemas de desempenho.Algo assim:
fonte
this.handleScroll = this.handleScroll.bind(this)
irá vincular issohandleScroll
ao componente, em vez de à janela.event.target.scrollingElement.scrollTop
Você pode passar uma função para o
onScroll
evento no elemento React: https://facebook.github.io/react/docs/events.html#ui-eventsOutra resposta semelhante: https://stackoverflow.com/a/36207913/1255973
fonte
Minha solução para criar uma barra de navegação responsiva (posição: 'relativa' quando não estiver rolando e corrigida ao rolar e não na parte superior da página)
Sem problemas de desempenho para mim.
fonte
para ajudar alguém aqui que percebeu os problemas de comportamento / desempenho atrasados ao usar a resposta de Austins e deseja um exemplo usando as referências mencionadas nos comentários, aqui está um exemplo que eu estava usando para alternar uma classe para um ícone de rolagem para cima / para baixo:
No método de renderização:
No método manipulador:
E adicione / remova seus manipuladores da mesma maneira que Austin mencionou:
docs sobre as refs .
fonte
this.scrollIcon.className = whatever-you-want
.className
ouclassList
. Além disso, eu não precisavawindow.addEventListener()
: usei o React'sonScroll
e é tão rápido, desde que você não atualize props / state!Descobri que não consigo adicionar com êxito o ouvinte de eventos, a menos que seja verdadeiro assim:
fonte
userCapture
: opcional. Um valor booleano que especifica se o evento deve ser executado na fase de captura ou subida. Valores possíveis: true - o manipulador de eventos é executado na fase de captura false - Default. O manipulador de eventos é executado na fase de bolhasUm exemplo usando classNames , React hooks useEffect , useState e styled-jsx :
fonte
com ganchos
fonte
Exemplo de componente de função usando useEffect:
Nota : Você precisa remover o ouvinte de eventos retornando uma função "limpeza" em useEffect. Caso contrário, sempre que o componente for atualizado, você terá um ouvinte de rolagem de janela adicional.
fonte
Se você estiver interessado em um componente filho que está rolando, este exemplo pode ser útil: https://codepen.io/JohnReynolds57/pen/NLNOyO?editors=0011
fonte
Resolvi o problema usando e modificando variáveis CSS. Dessa forma, não preciso modificar o estado do componente que causa problemas de desempenho.
index.css
Navbar.jsx
Navbar.module.css
fonte
Minha aposta aqui é usar componentes Function com novos ganchos para resolvê-lo, mas em vez de usar
useEffect
como nas respostas anteriores, acho que a opção correta seriauseLayoutEffect
por um motivo importante:Isso pode ser encontrado na documentação do React . Se usarmos
useEffect
e recarregarmos a página já rolada, a rolagem será falsa e nossa classe não será aplicada, causando um comportamento indesejado.Um exemplo:
Uma possível solução para o problema pode ser https://codepen.io/dcalderon/pen/mdJzOYq
fonte
useLayoutEffect
. Estou tentando ver o que você mencionou.useEffect
aqui em comparação comuseLayoutEffect
..Header--scrolled
classe às vezes, mas 100% de vezes.Header--scrolledLayout
é aplicado corretamente, graças a useLayoutEffect.Aqui está outro exemplo usando HOOKS fontAwesomeIcon e Kendo UI React
[! [Screenshot aqui] [1]] [1]
fonte
Atualização para uma resposta com React Hooks
Estes são dois ganchos - um para direção (para cima / para baixo / nenhum) e um para a posição real
Use assim:
Aqui estão os ganchos:
fonte
Para expandir a resposta de @ Austin, você deve adicionar
this.handleScroll = this.handleScroll.bind(this)
ao seu construtor:Isto dá
handleScroll()
acesso ao escopo adequado quando chamado do ouvinte de eventos.Lembre-se também de que você não pode executar
.bind(this)
os métodosaddEventListener
ouremoveEventListener
porque eles retornarão referências a diferentes funções e o evento não será removido quando o componente for desmontado.fonte