0

My socket.io chat app is basically fully functional but the react page is not updating when the message event is emitted to the group id. Currently I am using a map function to run through all of the messages in an array... Each time a message is sent it is saved in a database for future use, but that doesn't seem to be the problem because I removed that part and the react component still didn't update. Any help is greatly appreciated... code below --

// Import React dependencies.
import React, { Component } from "react";
import io from 'socket.io-client'
import axios from 'axios'
import Message from '../Message/Message'
import uuid from 'react-uuid'
// Import the Slate components and React plugin.

const ENDPOINT = 'http://localhost:5000/'
export const socket = io.connect(ENDPOINT)


export class LiveChat extends Component {
    constructor() {
        super()
        this.state = {
            messages: [],
            message: "",
            id: "",
            username: ""
        }
    }
    changeHandler = (e) => {
        this.setState({
            message: e.target.value
        })
        socket.emit('typing',)
    }

    clickHandler = () => {
        const data = {
            messageId: uuid(),
            username: this.state.username,
            groupId: this.state.id,
            message: this.state.message,
        }
        console.log(data.messageId)
        socket.emit('message', data)
    }
    async componentDidMount() {
        const { id } = this.props.match.params
        console.log(this.state)
        const response = await axios.get('http://localhost:5000/api/users/userInfo', { withCredentials: true })
        const messages = await axios.get(`http://localhost:5000/live/${id}`)
        console.log(messages.data)
        this.setState({
            messages: messages.data,
            username: response.data.user,
            id: id
        })
        console.log(this.state)
        socket.on('typing', data => {
            console.log(data)
        });
        socket.on(`message-${this.state.id}`, data => {
            console.log(data)
            this.state.messages.push(data)
        })
    }
    render() {
        return (
            <div>
                <input placeholder="message" type="text" onChange={e => this.changeHandler(e)} />
                <button onClick={this.clickHandler}>Submit</button>
                {this.state.messages.map((message) => (
                    <Message key={message.messageId} message={message} />
                ))}
            </div>
        )
    }
}

export default LiveChat;

relevant API code:

io.on("connection", (socket) => {
    console.log("New client connected");
    socket.on('new-operations', function (data) {
        groupData[data.groupId] = data.newValue;
        console.log(groupData[data.groupId])
        io.emit(`new-remote-operations-${data.groupId}`, data)
    })
    socket.on('typing-message', function (message) {
        io.emit('typing', "user is typing")
    })
    socket.on('message', function (data) {
        console.log(data)
        Chat.create({
            messageId: data.messageId,
            username: data.username,
            groupId: data.groupId,
            message: data.message
        })
        io.emit(`message-${data.groupId}`, data)
    })
    io.emit("init-value", initValue)
    socket.on("disconnect", () => {
        console.log("Client disconnected");
        clearInterval(interval);
    });
});
infecting
  • 523
  • 6
  • 10

1 Answers1

0

The problem is caused by the fact that setState is an asynchronous function. Because setState doesn't update the state immediately, in your codes, after you setState for id, you read it in the socket.on function, in this case, it is not guaranteed to get the updated state.

socket.on(`message-${this.state.id}`, data => {...

For more info, refer to this link below. setState doesn't update the state immediately

Eric
  • 1,279
  • 1
  • 11
  • 8