everyone !
I'm learning React by myself, and I'm stuck here where I'm doing a REST API for a Chat APP, when I POST a new message, the component don't refresh by itself, I have to refresh the page.
I managed to refresh it putting the idmessage and vmessage in the useEffect array, but it kept hitting the API, and I'm pretty sure this wasn't supposed to happen.
There may be a lot of wrong code here and a lot of different ways to do a better project, so I'm sorry if it's bad written.
P.S: Everything is mocked for the first and second contact
My MessagePage:
const MessagesPage = () => {
let [idmessage, setIdmessage] = useState([])
let [vmessage, setVmessage] = useState([])
useEffect(() => {
getIdMessage()
getVMessage()
}, [])
let url = 'http://127.0.0.1:8000'
let getIdMessage = async () => {
let response = await fetch(`${url}/api/messages/1/2/`)
let data = await response.json()
setIdmessage(data)
}
let getIdName = (idmessage) => {
return idmessage.map((m) => (
m.contact.name
))
}
let getVName = (vmessage) => {
return vmessage.map((m) => (
m.contact.name
))
}
let getVMessage = async () => {
let response = await fetch(`${url}/api/messages/2/1/`)
let data = await response.json()
setVmessage(data)
}
const messages = idmessage.concat(vmessage).sort((a,b) => {
return a.time.localeCompare(b.time);
}) // This is the way I found to make it like a real chat and not two different groups in a chat
return (
<>
<MessageHeader/>
<div className="card bg-dark card-body messages">
{messages.map((m, index) => (
m.contact.name === getIdName(idmessage)[0] ?
<MessageDetail messages={m} key={index} c={1}/>
: m.contact.name === getVName(vmessage)[0] ?
<MessageDetail messages={m} key={index} c={2}/>
: null
))
}
<SendMessage/>
</div>
</>
)
}
export default MessagesPage
Then my SendMessage Component:
const SendMessage = () => {
let [text, setText] = useState('')
let url = 'http://127.0.0.1:8000'
const handleChange = (e) =>{
setText(e.target.value)
}
const handleSubmit = (e) => {
e.preventDefault()
sendText()
setText('')
}
let sendText = async () => {
fetch(`${url}/api/messages/1/2/`, {
method: "POST",
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
"text": (text),
"contact": 1,
"other_contact": 2,
"state": false
})
})
}
return (
<div className="w-100 card-footer border bg-light textWrite">
<form className='m-0 p-0' onSubmit={handleSubmit} method="POST" autoComplete='off'>
<div className="row m-0 p-0">
<div className="col-11 m-0 p-1">
<input id="text" onChange={handleChange} className="mw-100 border rounded form-control" type="text" name="text" title="Send a Message" placeholder="Send a Message..." value={text} required/>
</div>
<div className="col-1 m-0 p-1">
<button id='sendText' className="btn btn-outline-secondary rounded border w-100" type='submit'><BsChatDots/></button>
</div>
</div>
</form>
</div>
)
}
export default SendMessage
The Serializer:
@api_view(['GET', 'POST'])
def detailMessages(request, pk, o_pk):
message = Message.objects.filter(contact=pk, other_contact=o_pk)
serializer = MessageSerial(message, many=True)
if request.method == 'GET':
return Response(serializer.data)
if request.method == 'POST':
data = request.data
contact = Contact.objects.get(id=data['contact'])
other_contact = Contact.objects.get(id=data['other_contact'])
message = Message.objects.create(
contact=contact,
other_contact=other_contact,
text=data['text'],
state=data['state']
)
serializer = MessageSerial(message, many=False)
return Response(serializer.data)
CodePudding user response:
If you want to make real time messages system without hitting the database each time, you should read about WebSocket in a simple word it is opening pool connection between multiple devices to send and receive data without closing the connection after send for example like http request and this data will always pass throw this connection(channel) without reloading or database hitting, you should read more about it to better understanding.
And if you want to use it in your project you can search about: react websocket and Django Channels
Best of luck