Quero criar um sistema de bate-papo e rolar automaticamente para baixo ao entrar na janela e quando novas mensagens aparecerem. Como rolar automaticamente para a parte inferior de um contêiner no React?
126
Como Tushar mencionou, você pode manter uma div falsa na parte inferior do seu bate-papo:
render () {
return (
<div>
<div className="MessageContainer" >
<div className="MessagesList">
{this.renderMessages()}
</div>
<div style={{ float:"left", clear: "both" }}
ref={(el) => { this.messagesEnd = el; }}>
</div>
</div>
</div>
);
}
e role até ele sempre que seu componente for atualizado (ou seja, estado atualizado à medida que novas mensagens são adicionadas):
scrollToBottom = () => {
this.messagesEnd.scrollIntoView({ behavior: "smooth" });
}
componentDidMount() {
this.scrollToBottom();
}
componentDidUpdate() {
this.scrollToBottom();
}
Estou usando o método Element.scrollIntoView padrão aqui.
this.messagesEnd.scrollIntoView()
funcionou bem para mim. Não havia necessidade de usarfindDOMNode()
.scrollToBottom(){this.scrollBottom.scrollIntoView({ behavior: 'smooth' })}
fazê-lo funcionar em versões mais recentesEu só quero atualizar a resposta para combinar com o novo
React.createRef()
método , mas é basicamente o mesmo, basta ter em mente acurrent
propriedade na ref criada:ATUALIZAR:
Agora que os ganchos estão disponíveis, estou atualizando a resposta para adicionar o uso dos
useRef
euseEffect
ganchos, a coisa real que faz a mágica (Reagir refs escrollIntoView
método DOM) permanece o mesmo:Também criou uma caixa de código (muito básica), se você deseja verificar o comportamento https://codesandbox.io/s/scrolltobottomexample-f90lz
fonte
this.messagesEnd.current
sempre existe. No entanto, é importante notar que a chamadathis.messagesEnd.current
antes da primeira renderização resultará no erro que você apontou. Thnx.this.messagesEnd
no seu primeiro exemplo no método scrollTo?useEffect
método precisa ser colocado com() => {scrollToBottom()}
. Muito obrigado de qualquer maneiraNão use
findDOMNode
Componentes de classe com ref
Componentes funcionais com ganchos:
fonte
behavior
(não é possível editar porque "as edições devem ter pelo menos 6 caracteres", suspiro).scrollIntoView
withsmooth
é muito ruim no momento.Graças a @enlitement
devemos evitar o uso
findDOMNode
, podemos usarrefs
para acompanhar os componentesreferência:
fonte
Você pode usar
ref
s para acompanhar os componentes.Se você souber uma maneira de definir o
ref
componente individual (o último), poste!Aqui está o que eu achei que funcionou para mim:
fonte
Faça referência ao seu contêiner de mensagens.
Encontre seu contêiner de mensagens e torne seu
scrollTop
atributo igualscrollHeight
:Evocar o método acima em
componentDidMount
ecomponentDidUpdate
.É assim que estou usando isso no meu código:
fonte
O react-scrollable-feed rola automaticamente para baixo até o elemento mais recente se o usuário já estava na parte inferior da seção rolável. Caso contrário, ele deixará o usuário na mesma posição. Eu acho que isso é bastante útil para componentes de bate-papo :)
Acho que as outras respostas aqui forçarão a rolagem toda vez, não importa onde esteja a barra de rolagem. O outro problema
scrollIntoView
é que ele rolará a página inteira se a sua div rolável não estiver em exibição.Pode ser usado assim:
Apenas certifique-se de ter um componente wrapper com um específico
height
oumax-height
Isenção de responsabilidade: eu sou o proprietário do pacote
fonte
Criei um elemento vazio no final das mensagens e rolei para esse elemento. Não há necessidade de acompanhar as referências.
fonte
Se você quiser fazer isso com o React Hooks, esse método pode ser seguido. Para um div fictício, foi colocado na parte inferior do chat. useRef Hook é usado aqui.
Referência da API Hooks: https://reactjs.org/docs/hooks-reference.html#useref
fonte
A maneira mais fácil e melhor que eu recomendaria é.
Versão do My ReactJS: 16.12.0
Estrutura HTML dentro da
render()
funçãoscrollToBottom()
função que obterá referência do elemento. e role de acordo com ascrollIntoView()
função.e chame a função acima dentro
componentDidMount()
ecomponentDidUpdate()
para mais explicações sobre a
Element.scrollIntoView()
visita developer.mozilla.orgfonte
Não consegui obter nenhuma das respostas abaixo para funcionar, mas js simples fizeram o truque para mim:
fonte
Exemplo de trabalho:
Você pode usar o
scrollIntoView
método DOM para tornar um componente visível na exibição.Para isso, ao renderizar o componente, basta fornecer um ID de referência para o elemento DOM usando o
ref
atributo Em seguida, use o métodoscrollIntoView
nocomponentDidMount
ciclo de vida. Estou apenas colocando um código de exemplo funcional para esta solução. A seguir, é apresentado um componente sempre que uma mensagem é recebida. Você deve escrever códigos / métodos para renderizar esse componente.Aqui
this.props.message.MessageId
está o ID exclusivo da mensagem de chat específica passada comoprops
fonte
fonte
Eu gosto de fazer da seguinte maneira.
fonte
obrigado 'metakermit' por sua boa resposta, mas acho que podemos melhorar um pouco, para rolar para baixo, devemos usar o seguinte:
mas se você quiser rolar para cima, use:
e esses códigos são comuns:
fonte
Como outra opção, vale a pena examinar o componente de rolagem de reação .
fonte
Usando
React.createRef()
fonte
É assim que você resolveria isso no TypeScript (usando a ref para um elemento de destino para o qual você rola):
Para obter mais informações sobre como usar ref com React e Typescript, você pode encontrar um ótimo artigo aqui .
fonte
Versão completa (datilografada):
fonte
Property 'scrollIntoView' does not exist on type 'RefObject<unknown>'.
eType 'HTMLDivElement | null' is not assignable to type 'RefObject<unknown>'. Type 'null' is not assignable to type 'RefObject<unknown>'.
então ...