Stream Chat Messages in Real-time in Next.js from Fauna

Shadid Haque
InstructorShadid Haque
Share this video with your friends

Social Share Links

Send Tweet
Published 3 months ago
Updated 3 hours ago

To stream messages, we'll implement logic very similar to how we stream the creation of rooms from earlier.

First, we need to convert MessageList into a client component. We'll get an interesting error saying that only plain objects can be passed to client components from server components. This happens because the response we get back from Fauna is pretty complex. To fix this error we'll create a simple messages array and pass that down to the MessageList component.

In the MessageList component we'll create a useEffect that will initiate a Fauna stream within a ref and push new messages into state that we are holding in the component.

[00:00] So back in our code, we're gonna go to our message list component, and we're going to turn this component into a client component. And we're just gonna write use client at the top. So back in our application, we're gonna navigate to a room and we're gonna get an error. And this error says that only plain objects [00:20] can be passed to a client component. Now this is because the response that we get from our fauna database is a complex object. It has a lot of nested fields. So we just have to simplify that object and pass it to our client component. To fix this issue, we're gonna go back to our code. We're gonna go to the page [00:40] component that is under rooms ID, And we're going to create a new messages array from the response that we get from fauna. Now using the map function here, I'm just going to pick the text and the ID for each message. [01:04] And then we just plug the messages into the message list component. And in message list component, now we can remove the data. Now back in our browser, we're gonna refresh it, and everything should work again. So back in our message [01:24] list component, we're going to import user state from React. Next, we create a state variable called all messages. And the initial state will be the messages. Next in our JSX, we update the messages [01:44] to state variable all messages. Next, we're gonna go and import client and FQL from fauna. And we'll initialize a new fauna client. Next, we're [02:04] gonna import useEffect and useRef from React. And then we create a new ref object called stream ref with an initial value of null. And then we're gonna create our useEffect. And inside we're gonna check if our font client is already initialized. [02:25] And we will call a function called getMessage. So let's go ahead and implement this getMessage function. We're gonna add a try catch here. And then inside the try block, we're gonna write const stream await [02:45] client dot stream, and then round bracket. And then inside round bracket, we're gonna write SQL, and then back ticks. And then inside back ticks, we're gonna write room dot by ID, and then we're gonna pass in the ID of the room. And let's just put this into the next [03:04] line. And I'm going to assign this to a new variable called room. And next, we're gonna write message dot where and then dot room equals equals room and then dot to stream. And this will start to streaming the messages. We're streaming all the messages that belongs [03:24] to this room. So whenever a message is added or gets deleted from this room, we're gonna get notification in real time. And then we're gonna write stream ref dot current is equals stream. And next, we're gonna wrap this entire logic into a if statement. And the if block executes when [03:45] stream ref dot current is undefined. Now putting it inside this if block will prevent from subscribing to the same event twice. Okay. So next, we're gonna loop through the stream events. [04:05] So I'm gonna write a for of loop here to each event from the stream, and we're gonna console log the event. And then we're gonna write a switch statement, and we're gonna switch on event type. And then [04:25] we are going to look for the add case, and we'll also add a default case here. Whenever a new message is added to this room, the add case code block executes. So we're going to update the state of this [04:45] component when a new message is added to this room. So we check if the message already exists in our state. If it doesn't, then we're just going to add the message. [05:15] If it does, we will simply just return the previous state. So back in our app, we actually get this error that says params is not defined, and it's coming from message list components. So let's go ahead and fix this. Now as you can see, our message list component is [05:35] not a page component, so it does not have access to the params prompts. So we're gonna go back to our room page component. And here, we actually have access to the params. So we're just gonna pass the ID of the room down the message list [05:54] component as a props. Back in our message list component, we can destructure room ID from props, and then we can pass this into the SQL query. And that should fix all our issues, and [06:14] now we should be able to create messages and view them in real time.

egghead
egghead
~ 13 minutes ago

Member comments are a way for members to communicate, interact, and ask questions about a lesson.

The instructor or someone from the community might respond to your question Here are a few basic guidelines to commenting on egghead.io

Be on-Topic

Comments are for discussing a lesson. If you're having a general issue with the website functionality, please contact us at support@egghead.io.

Avoid meta-discussion

  • This was great!
  • This was horrible!
  • I didn't like this because it didn't match my skill level.
  • +1 It will likely be deleted as spam.

Code Problems?

Should be accompanied by code! Codesandbox or Stackblitz provide a way to share code and discuss it in context

Details and Context

Vague question? Vague answer. Any details and context you can provide will lure more interesting answers!

Markdown supported.
Become a member to join the discussionEnroll Today