# Adding Realtime capabilities using socket

{% embed url="<https://www.youtube.com/watch?v=oIQI-KTO6mw>" %}
Add Realtime Capabilities
{% endembed %}

## Setting Up UI

1. Create a new UI file named `rt-message` within the `main-features` folder and set its path to `/`.
2. Add three buttons: Send Message, Leave Room, and Join Room.
3. Import `Space` and `Input` components, and wrap the buttons and input field within the `Space` component.
4. Add an input field and set the width of the input field to 300 for better usability.
5. Create a `div` with a height of 100 to display the last message.

### State Management

1. Initialize two states to manage the last message and the input value.
2. Incorporate these states within the UI, ensuring their proper rendering and functionality.

> Refer the code below:

{% code title="rt-message.tsx" %}

```tsx
import React, { useState } from "react"
import { Button, Input, Space } from "antd"

export default function Component(props: any) {
    const [msg, setMsg] = React.useState("")
    const [input, setInput] = React.useState("")

    return (
        <div>
            <div style={{ height: 100 }}>
                <p>Last Message:</p>
                <h1>{msg}</h1>
            </div>

            <Space>
                <Input
                    value={input}
                    onChange={(e) => setInput(e.target.value)}
                    style={{ width: 300 }}
                />

                <Button>Send Message</Button>

                <Button>Leave Room</Button>

                <Button>Join Room</Button>
            </Space>
        </div>
    )
}
```

{% endcode %}

## Backend Configuration

1. Create a backend function named `send-msg`.
2. Import `io` and emit a new message received from the frontend.

> Refer the snippet below.

{% code title="send-msg.server.tsx" %}

```tsx
import { createBackendFunction, io } from "@magicjs.dev/backend"

export default createBackendFunction(async function (msg: string) {
    io().emit('new-message', msg)

    return "Message from server"
})
```

{% endcode %}

* The function accepts a parameter `msg` of type string.
* Inside the function body:
  * It uses the `io` function to emit a message with the event name `'new-message'` and the provided `msg` parameter.

Configure the frontend to call this function upon clicking the Send Message button, passing the input value and resetting it afterward.

> Refer the snippet below.

```tsx
<Button onClick={() => sendMsgServer(input).then(() => {
    setMsg(input);
    setInput('');
})}>
    Send Message
</Button>
```

{% hint style="info" %}
Import the `sendMsgServer` from `"./send-msg.server".`
{% endhint %}

## Real-Time Messaging

1. Import `{ useSocket }` from `'@magicjs.dev/frontend'`;
2. Utilize the `useSocket()` hook to establish socket connection.
3. Implement a `useEffect()` hook to subscribe to incoming messages and update the state accordingly.
4. Ensure proper subscription management by unsubscribing within the hook.

> Refer the snippet below.

{% code title="In rt-message.tsx" %}

```tsx
const socket = useSocket();

React.useEffect(() => {
    const unsub = socket.subscribe("new-message", (msg) => {
        setMsg(msg)
    })
    return unsub
})
```

{% endcode %}

## Room Restriction

1. Modify the backend to emit messages only to a specific room, e.g., "secret-room".
2. Allow users to join and leave the room by invoking `socket.joinRoom()` and `socket.leaveRoom()` respectively in the frontend.

> Refer the snippets below.

{% code title="send-msg.server.tsx" %}

```typescript
import { createBackendFunction, io } from "@magicjs.dev/backend"

export default createBackendFunction(async function (msg: string) {
    io().to("secret-room").emit("new-message", msg)

    return "Message from server"
})
```

{% endcode %}

{% code title="In rt-message.tsx" %}

```tsx
<Button onClick={() => socket.leaveRoom("secret-room")}>
    Leave Room
</Button>

<Button onClick={() => socket.joinRoom("secret-room")}>
    Join Room
</Button>
```

{% endcode %}

<details>

<summary>Expand for Tailwind styled code.</summary>

{% code title="rt-message.tsx" lineNumbers="true" %}

```typescript
import React from 'react';
import sendMsgServer from "./send-message.server";
import { useSocket } from '@magicjs.dev/frontend';

export default function Test() {
  const [msg, setMsg] = React.useState("")
  const [input, setInput] = React.useState("")
  const socket = useSocket();

  React.useEffect(() => {
    const unsub = socket.subscribe("new-message", (msg) => {
      setMsg(msg)
    })
    return unsub
  })

  return (
    <div className='flex flex-col justify-center items-center min-h-screen'>
      <div>
        <div className='text-[40px] text-[#212121] mb-10'>Latest Message:</div>
        <div className='h-[80px]'>
          <h1 className='text-[56px] font-medium text-[#147E1D]'>{msg}</h1>
        </div>
        <input
          value={input}
          onChange={(e) => setInput(e.target.value)}
          className='w-full border border-[#C1C1C1] rounded-[8px] mt-10'
        />
        <div className='flex flex-row gap-[33px] mt-10'>
          <button
            onClick={() => sendMsgServer(input).then(() => {
              setMsg(input);
              setInput('');
            })}
            className='text-[25px] text-[#151515] border border-[#BFBFBF] rounded-[10px] px-[62px] py-[15px] hover:opacity-70'
          >
            Send Message
          </button>
          <button
            onClick={() => socket.joinRoom("secret-room")}
            className='text-[25px] text-[#151515] border border-[#BFBFBF] rounded-[10px] px-[62px] py-[15px] hover:opacity-70'
          >
            Leave Room
          </button>
          <button
            onClick={() => socket.joinRoom("secret-room")}
            className='text-[25px] text-[#151515] border border-[#BFBFBF] rounded-[10px] px-[62px] py-[15px] hover:opacity-70'
          >
            Join Room
          </button>
        </div>
      </div>
    </div>
  )
}
```

{% endcode %}

</details>

## Testing

1. Open two browsers with the same page.
2. Test sending messages within the room, ensuring they are received in real-time only by members of the room.

<figure><img src="/files/f0oq07BQ3fJWQBT3XiWC" alt=""><figcaption><p>Output in 2 browsers.</p></figcaption></figure>

:tada: Congratulations! You have successfully implemented real-time messaging capabilities using MagicJS's socket feature.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://skyslit.gitbook.io/magicjs/basic-guide/adding-realtime-capabilities-using-socket.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
