Scroll anchoring: load history without a jump, don't yank a reader
Each row is 30 px in a 120 px box. Loading 5 older messages adds 150 px above, and the layout effect adds exactly that to scrollTop, so the same row stays on top. A reader scrolled into history isn't moved; they get a badge instead. overflow-anchor: none turns off the browser's own anchoring so you see the React code doing it.
A chat client keeps a live two-way connection, shows your message instantly and then confirms it, orders messages by the server's sequence number rather than by arrival, keeps the scroll where the reader expects, counts unread messages, queues sends while offline and shows who is online and typing.
Change the code and press Run (Ctrl+Enter). Predict what will happen first, then break it on purpose and read what changes. Your edits are saved and match the lesson page.
Ready for more? This phase has 5 hands-on exercises with automatic checks.
Practice questions
Write the code in the editor, run it, then open the model answer to compare.
Show a delivery tick for delivered (✓✓) when a fake receipt event arrives for a message.
Add a typing indicator: when a fake typing event arrives, show Ravi is typing… and hide it 2 seconds after the last event.
Explain it without notes
How do you order chat messages correctly?
Walk through what happens when a user sends a message on a flaky connection.
How would you handle scrolling in a chat view?
How do unread counts and read receipts work?
What happens when the WebSocket disconnects and reconnects?
Preview
Console
Nothing logged yet.Expected console output
mounted at bottom, scrollTop 180, top row Message 17
after loading 5 older: scrollTop 330, top row Message 17
reader kept at scrollTop 0, badge: 1 new message ↓