Socket.IO: Is it possible to emit and listen for events in the same client

Like the title says, I wanna know if I can establish a socket.io connection in my frontend and then make the same instance emit messages. Then listen for those same messages within the frontend? I am working on a chat app and want to enable real-time messaging. So according to my component code below, when a user sends a message, the handleSubmit function is called. Inside the handleSubmit function I’m making an AJAX request to upload the text message to the database through the backend server. For receving messages, currently, I only have a useEffect() hook which will execute fetchChats(). But this component currently doesn’t support real-time updates. So my question is how can I setup socket.io in this component. I would want the io connection to emit a message with message data including “recipientEmail” (which is the email id of the user we’re texting to). And then also constantly keep listening for a message, once a message is received it will check whether recipientEmail in the message’s metadata is equal to client (here I’m now talking from the 2nd user’s perspective, where client is the second user.)

My current component is as follows:

import { useEffect, useState } from 'react';
import { Button, ChatBubble, Navbar, Textarea } from 'react-daisyui';
import axios from 'axios';
import io from 'socket.io-client';

const api = `http://localhost:8000`;

function ChatWindow({ recipientNickname, recipientEmail }) {

    const client = window.localStorage.getItem('mail');
    const [chats, setChats] = useState([]);
    const [message, setMessage] = useState('');
    const [counter, setCounter] = useState(0);

    const socket = io() // socket.io connection on the same location as the frontend, i.e. localhost:3010

    async function fetchChats() {
        try {
            const response = await axios.get(`${api}/users/messages?client=${client}&recipient=${recipientEmail}`);
            if (response.data)
                setChats(response.data);
            else
                setChats([]);
        } catch (e) {
            console.log(e);
        }
    }

    useEffect(() => {
        fetchChats();
    }, [recipientEmail]);

    useEffect(() => {
        if (counter > 0) {
            fetchChats();
        }
    }, [counter]);

    const getCurrentTimestamp = () => {
        // ...
    };

    const handleSubmit = async (e) => {
        e.preventDefault();
        if (message) {
            const timestamp = getCurrentTimestamp()

            //posting the message to the database through the backend server
            await axios.post(`${api}/users/messages?client=${client}&recipient=${recipientEmail}&message=${message}&timestamp=${timestamp}`);

            setMessage('');
            setCounter((prevCounter) => prevCounter + 1);
            await fetchChats();
            try {
                // trying to emit a new message
                const res = socket.emit('new-message', { recipientEmail, message, timestamp })
                    console.log(res)
                console.log('Message emitted')
            } catch(e) {
                console.log('Couldnt emit message:n'+e)
            }
        }
    }

    // listening for new messages then comparing recipientEmail with client
    useEffect(() => {
        socket.on('new-message', (data) => {
            console.log('Received new message data:n'+data)
          if (data.recipientEmail === client) {
            setChats((prevChats) => [...prevChats, data]);
          }
        });
        return () => socket.disconnect();
      }, []);

    return (
        <div style={{ marginLeft: 250, marginRight: 20, zIndex: 1 }}>
            <div className='chats' style={{ maxHeight: '75vh', overflowY: 'auto' }}>
                {chats.map((message, index) => (
                    <ChatBubble key={index} end={message.client === client}>
                        <ChatBubble.Message>{message.message}</ChatBubble.Message>
                        {message.client === client ? <ChatBubble.Footer>{message.footer}</ChatBubble.Footer> : <></>}
                    </ChatBubble>
                ))}
            </div>
            <div style={{ position: 'absolute', bottom: 10, left: 250, right: 20 }}>
                <form onSubmit={handleSubmit}>
                    <Textarea
                        rows={1}
                        style={{ width: '100%', borderRadius: 10, margin: 5 }}
                        placeholder='Send a message'
                        className='join-item msg-input'
                        value={message}
                        onChange={(e) => setMessage(e.target.value)}
                        onKeyDown={(e) => {
                            if (e.key === 'Enter' && !e.shiftKey) {
                                e.preventDefault();
                                handleSubmit(e);
                            }
                        }}
                    />
                </form>
            </div>
        </div>
    );
}

export default ChatWindow

I tried implementing a socket.io connection on my own (as in the code above), but it doesn’t work. The message gets emitted and the result of console.log(res) (after emitting the message) gives something like this:

Socket {connected: false, recovered: false, receiveBuffer: Array(0), sendBuffer: Array(1), _queue: Array(0), …}

which clearly states that the connection couldn’t be established.