How I brought Yahoo Chat back to life in 5 hours: Part 1 — The Easy Stuff
I don’t know if you guys remember Yahoo Chat rooms, but they were everything back in 2005. Even though I haven’t used a chat room in almost 10 years, I still remember them vividly and I was just wracking my brain on what project to make when — YES. Because this is why I became a software developer, right?
The Set Up
We have to start every project somewhere, and I wanted that place to be a react application. I fired up create react-app in my terminal, added a directory called frontend, added redux and react-redux (the space in-between allows both yarn packages to install at the same time), and then started my react server on localhost.
yarn create react-app chatroom
cd chatroommkdir chatroom-frontend
cd chatroom-frontend yarn add redux react-redux
yarn start
I knew that I wanted my chatroom to have a header, a list of visitors on the right side, and the chat and text boxes on the left side, so I drew up a very basic wireframe and organized my components and containers for ease. I decided to use Redux in order to make state management easier, but if you were going to make this project without Redux, I think passing state and props would be fairly simple to manage.
Redux
I decided that my initial store state only needed to keep track of three things: username, users, and messages. I made TextBox a controlled form so it keeps track of the message being typed and then dispatches it to the messagesReducer, adding it to the end of my messages array in store.
I also wanted this application to randomly assign a username to people as they logged in, so I created a variable called username in App which took the string “NewUser” + a randomly generated integer between 1 and 1000 and then dispatched it to Username before adding it to the array of Users in store.
I knew that I needed to conditionally render both messages and users. For messages, I used mapStateToProps in MessagesContainer.js and passed the messages to both of the children components. For users, I used mapStateToProps in App.js and passed the users as a prop all the way down to the Users component. Passing the props down allowed me to access the users in the MessagesContainer, allowing conditional rendering in order for it to say “Me:” instead of my username on the messages I had sent.
Auto-Scrolling
This is when I ran into my first “issue”. I say it like that because it wasn’t really a problem, but more of a snafu that I wanted to resolve as quickly as possible for user experience. I knew that new messages needed to always take priority, so how could I force the chat box to always stay scrolled down instead of prioritizing the oldest messages at the top of the chat box?
Yep, you probably didn’t guess it either, because I had to look it up.
handleObserverForScroll = () => {
let messagesList = document.querySelector('.message-list')
let observer = new MutationObserver(() =>
this.scrollToBottom(messagesList)
)
let config = {childList: true}
observer.observe(messagesList, config)
}scrollToBottom = (messagesList) => {
messagesList.scrollTop = messagesList.scrollHeight
}
The handleObserverForScroll function first selects the div that surrounds the messages and sets it to a variable called messagesList.
It then adds a MutationObserver, named observer, that invokes a callback function when DOM changes occur (which is great since it’s going to be keeping an eye out for new messages!), calling the anonymous function to scrollToBottom and passing in the messagesList.
The scrollToBottom function takes the messagesList and sets the scrollTop (the number of pixels an element’s content is scrolled vertically) to the scrollHeight (the height of an element in pixels, including padding, but not the border, scrollbar or margin) which, from what I can tell, just tells the scrollbar to move down to the bottom position.
After that, we made a variable called config to tell the MutationObserver to call the function every single time the messagesList changes.
Lastly, we tell the observer to observe the messagesList (the box with the messages) with the configuration of always staying on… and BOOM. Yay programming! It works!
What Next?
It’s so great that we have a beautiful chat application that, for all intents and purposes, works pretty well. But what are we missing? Yep, that’s right. How can users get online and chat with each other? Click here for part 2 where I explain (in detail!!) how to set up a WebSocket!