Всех приветствую. Решил написать веб чат на Django&Channels, React&Websocket. Я успешно подключаюсь к сокету и отключаюсь от него, то есть при входе и выходе из комнаты нет проблем, так вот к сути проблемы когда я захожу в комнату происходит подключение, отправляю сообщение, оно принимается бэком и возвращается, выхожу из комнаты, соединение соответственно разрывается и при повторном заходе в ту же комнату или любую другую ловлю такую ошибку
Failed to execute 'send' on 'WebSocket': Still in CONNECTING state.
Room.jsx
import React, { useEffect, useRef, useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import '../App.css'
import Container from 'react-bootstrap/Container';
import Row from 'react-bootstrap/Row';
// import Col from 'react-bootstrap/Col';
import Button from 'react-bootstrap/Button';
import { ServerMessage } from '../Redux-apps/RdxContext';
const Room = () => {
const name = useSelector(state => state.nameOfRoom.value)
const dispatch = useDispatch()
const message = useSelector(state => state.messageFromServer.message)
const [text, setText] = useState('')
const [fromBack, setFromBack] = useState('')
const socketRef = useRef(null)
const formOnSubmit = (elem) => {
elem.preventDefault()
elem.target.reset()
dispatch(ServerMessage(text))
}
useEffect(() => {
if (name.length > 0) {
// Создаем объект WebSocket только один раз
socketRef.current = new WebSocket(`ws://127.0.0.1:8000/ws/room/${name}/`)
socketRef.current.onopen = () => {
console.log('Подключение установлено')
}
socketRef.current.onclose = () => console.log('Подключение разорвано')
socketRef.current.onmessage = (msg) => {
let data = JSON.parse(msg.data)
console.log(data.type)
setFromBack(data.message)
}
}
console.log(socketRef.current.readyState)
// Закрываем соединение при размонтировании компонента
return () => {
if (socketRef.current) {
socketRef.current.close()
}
}
}, [name])
useEffect(() => {
if (socketRef.current && message) {
socketRef.current.send(
JSON.stringify({
'message': message
})
)
}
})
console.log(fromBack)
return (
<Container>
<Row>
<div className='mt-5'>
<div className='chat-window'>
<div className="message-blue">
<p className="message-content">{fromBack}</p>
</div>
</div>
<div>
<form onSubmit={formOnSubmit}>
<input
onChange={(e) => setText(e.target.value)}
className='chat-input mt-5'
type="text"
/>
<Button type='submit' variant="outline-secondary" id="button-addon2">Button</Button>
</form>
</div>
</div>
</Row>
</Container>
)
}
export default Room
consumer.py
import json
from asgiref.sync import sync_to_async
from channels.generic.websocket import AsyncWebsocketConsumer
from channels.db import database_sync_to_async
from django.forms.models import model_to_dict
from .models import Message, Room
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.room_name = self.scope['url_route']['kwargs']['room_name']
self.room_group_name = f'chat_{self.room_name}'
self.create_room = await database_sync_to_async(Room.objects.get_or_create)(slug=self.room_name)
print(f'Путь до комнаты: {self.scope["path"]}')
await self.channel_layer.group_add(
self.room_group_name,
self.channel_name
)
await self.accept()
# await self.send(json.dumps('sucessfully connected!'))
async def disconnect(self, close_code):
await self.channel_layer.group_discard(
self.room_group_name,
self.channel_name
)
@database_sync_to_async
def get_messages(self):
messages = Message.objects.filter(room__room=self.room_name)
msg = []
for m in messages:
msg.append(m)
return msg
@database_sync_to_async
def create_message(self, message, room):
return Message.objects.create(message=message, room=room)
@database_sync_to_async
def get_room(self):
return Room.objects.get(slug=self.room_name)
async def receive(self, text_data=None, bytes_data=None):
data = json.loads(text_data)
message = data['message']
room = await self.get_room()
save_message = await self.create_message(message, room=room)
print(f'Receive: {message}')
await self.channel_layer.group_send(
self.room_group_name,
{
'type': 'chat_message',
'message': message
}
)
async def chat_message(self, event):
message = event['message']
print(f'Send: {message}')
await self.send(text_data=json.dumps(
{
'message': message
}
))
в consumer.py есть не используемые вещи связанные с получением и передачей данных из бд, на них можете не обращать внимание.