React useState() — добавление нового элемента в массив не работает

#javascript #reactjs #typescript #react-native #socket.io

Вопрос:

Я создаю приложение для чата с помощью React native и сокета.io но когда я получаю сообщение, я хочу добавить его в массив сообщений. Но почему-то это не работает. Он заменяет элементы массива вместо того, чтобы подтолкнуть/добавить в него элемент.

 const [messages, setMessages] = useState([])


useEffect(() => {
    const id = data.id
    receiveMessage(id)
}, []);

async function receiveMessage(id){
    await message.init(id)
    message.recieveMessage(message=>{
        setMessages([...messages, message])//something is wrong over here
    })
}


async function send(){
    if(text){
        message.sendMessage(text, data=>{
            setMessages([...messages, data])//this part works perfectly
        })
    }
    setText(null)
}
 

Вот Messages object :

 export class Message {
    private socket: Socket
    private room: string
    constructor(socketio: Socket){
        this.socket = socketio
        this.room = null
    }
    async init(id: string){
        if(id === this.room) {
            return
        }
        this.room = id
        this.socket.emit("join", {id: id, session: await getSessionToken()})
        
        const prom = new Promise((res, rej)=>{
            this.socket.on("joined", message=>{
                res("done")
            })
        })
        await prom
        return "done"
    }
    public sendMessage(message: string, callback){
        const socket = this.socket
        socket.emit("message", message)
        socket.on("sent", callback)
    }
    public recieveMessage(callback){
        const socket = this.socket
        socket.on("receive message", callback)
    }
}
 

Ответ №1:

Возможно ли это потому, что вы не передаете предыдущее состояние setMessages вызову?

Может быть, вместо этого стоит попробовать что-то подобное

 async function receiveMessage(id) {
  await message.init(id)

  message.recieveMessage(message => {
    setMessages(prevMessages => [...prevMessages, message])
  })
}

 

Комментарии:

1. Спасибо, что это сработало. Но я не понимал разницы между setMessages(prevMessages => [...prevMessages, message]) и setMessages([...messages, message])

2. @Обновление функционального состояния BilljeshBaidya, оно обновляется из предыдущего состояния, в то время как обычное обновление захватывает все, что было закрыто по значению messages , когда был создан обратный вызов.