Chcę zbudować system czatu i automatycznie przewijać do dołu po wejściu do okna i kiedy przychodzą nowe wiadomości. Jak automatycznie przewijać do dołu kontenera w Reakcie?
127
Jak wspomniał Tushar, na dole czatu możesz umieścić fikcyjny element div:
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>
);
}
a następnie przewiń do niego przy każdej aktualizacji komponentu (tj. stan aktualizowany po dodaniu nowych wiadomości):
scrollToBottom = () => {
this.messagesEnd.scrollIntoView({ behavior: "smooth" });
}
componentDidMount() {
this.scrollToBottom();
}
componentDidUpdate() {
this.scrollToBottom();
}
Używam tutaj standardowej metody Element.scrollIntoView .
this.messagesEnd.scrollIntoView()
działało dobrze dla mnie. Nie było potrzeby używaniafindDOMNode()
.scrollToBottom(){this.scrollBottom.scrollIntoView({ behavior: 'smooth' })}
aby działała w nowszych wersjachChcę tylko zaktualizować odpowiedź, aby pasowała do nowej
React.createRef()
metody , ale w zasadzie jest taka sama, pamiętaj tylko ocurrent
właściwości w utworzonym ref:AKTUALIZACJA:
Teraz, gdy hooki są dostępne, aktualizuję odpowiedź, dodając użycie haków
useRef
iuseEffect
, prawdziwa rzecz, która robi magię (refs React iscrollIntoView
metoda DOM) pozostaje taka sama:Stworzyłem również (bardzo podstawowe) pole kodów, jeśli chcesz sprawdzić zachowanie https://codesandbox.io/s/scrolltobottomexample-f90lz
źródło
this.messagesEnd.current
zawsze istnieje. Niemniej jednak ważne jest, aby zauważyć, że wywołaniethis.messagesEnd.current
przed pierwszym renderowaniem spowoduje wskazany błąd. Thnx.this.messagesEnd
w Twoim pierwszym przykładzie w metodzie scrollTo?useEffect
Sposób muszą być umieszczone z() => {scrollToBottom()}
. W każdym razie bardzo dziękujęNie używać
findDOMNode
Komponenty klasy z ref
Elementy funkcyjne z haczykami:
źródło
behavior
(nie można edytować, ponieważ „edycja musi mieć co najmniej 6 znaków”, westchnij).scrollIntoView
withsmooth
jest obecnie bardzo słabe.Dzięki @enlitement
powinniśmy unikać używania
findDOMNode
, możemy użyćrefs
do śledzenia komponentówodniesienie:
źródło
Możesz użyć
ref
s do śledzenia komponentów.Jeśli wiesz, jak ustawić
ref
pojedynczy komponent (ostatni), napisz!Oto, co okazało się dla mnie skuteczne:
źródło
reakcja-przewijalne-źródło automatycznie przewija w dół do ostatniego elementu, jeśli użytkownik był już na dole przewijalnej sekcji. W przeciwnym razie pozostawi użytkownika w tej samej pozycji. Myślę, że jest to całkiem przydatne w przypadku komponentów czatu :)
Myślę, że inne odpowiedzi tutaj wymuszą przewijanie za każdym razem, bez względu na to, gdzie był pasek przewijania. Innym problemem
scrollIntoView
jest to, że przewija całą stronę, jeśli nie widać przewijalnego elementu div.Można go używać w następujący sposób:
Po prostu upewnij się, że masz komponent opakowania z określonym
height
lubmax-height
Zastrzeżenie: jestem właścicielem pakietu
źródło
Odwołaj się do kontenera wiadomości.
Znajdź kontener wiadomości i wyrównaj jego
scrollTop
atrybutscrollHeight
:Wywołaj powyższą metodę na
componentDidMount
icomponentDidUpdate
.Oto jak używam tego w moim kodzie:
źródło
Utworzyłem pusty element na końcu wiadomości i przewinąłem do tego elementu. Nie ma potrzeby śledzenia referencji.
źródło
Jeśli chcesz to zrobić z React hookami, możesz zastosować tę metodę. Fikcyjny div został umieszczony na dole czatu. useRef Hook jest używany tutaj.
Dokumentacja interfejsu API hooków: https://reactjs.org/docs/hooks-reference.html#useref
źródło
Najłatwiejszy i najlepszy sposób, który bym polecił, to.
Moja wersja ReactJS: 16.12.0
Struktura HTML wewnątrz
render()
funkcjiscrollToBottom()
funkcja, która uzyska odniesienie do elementu. i przewijaj zgodnie zscrollIntoView()
funkcją.i wywołaj powyższą funkcję wewnątrz
componentDidMount()
icomponentDidUpdate()
aby uzyskać więcej informacji na temat
Element.scrollIntoView()
odwiedź developer.mozilla.orgźródło
Nie udało mi się uzyskać żadnej z poniższych odpowiedzi, ale proste js załatwiły sprawę:
źródło
Przykład roboczy:
Możesz użyć
scrollIntoView
metody DOM , aby wyświetlić komponent w widoku.W tym celu podczas renderowania komponentu po prostu podaj identyfikator odniesienia dla elementu DOM za pomocą
ref
atrybutu. Następnie użyć metodyscrollIntoView
wcomponentDidMount
cyklu życia. Właśnie umieszczam działający przykładowy kod tego rozwiązania. Poniżej przedstawiono komponent renderujący za każdym razem, gdy otrzymana wiadomość. Powinieneś napisać kod / metody renderowania tego komponentu.Oto
this.props.message.MessageId
unikalny identyfikator konkretnej wiadomości czatu przekazanej jakoprops
źródło
źródło
Lubię to robić w następujący sposób.
źródło
dziękuję „metakermit” za jego dobrą odpowiedź, ale myślę, że możemy to trochę ulepszyć, aby przewinąć do dołu, powinniśmy użyć tego:
ale jeśli chcesz przewijać do góry, użyj tego:
i te kody są wspólne:
źródło
Jako kolejną opcję warto przyjrzeć się komponentowi React scroll .
źródło
Za pomocą
React.createRef()
źródło
Oto jak można to rozwiązać w TypeScript (używając ref do docelowego elementu, do którego przewijasz):
Aby uzyskać więcej informacji na temat używania ref z React i Typescript, możesz znaleźć świetny artykuł tutaj .
źródło
Pełna wersja (maszynopis):
źródło
Property 'scrollIntoView' does not exist on type 'RefObject<unknown>'.
aType 'HTMLDivElement | null' is not assignable to type 'RefObject<unknown>'. Type 'null' is not assignable to type 'RefObject<unknown>'.
więc ...