Joel
Joel

Reputation: 1640

React state resetting

I have a basic component which subscribes to an EventEmitters event. All it is meant to do, is accumulate an array of messages.

What is happening however, is the message array only ends up containing the latest message.

Here's the component source:

export const MessageList = ({serverId, connection}) =>
{
    var [messages, setMessages] = useState([]);

    const appendSystem = (message) =>
    {
        console.log("Appending " + message);
        console.log(messages);

        setMessages([...messages, message]);
    }

    useEffect(() =>
    {
        connection.on('system', appendSystem);

        return () => connection.removeListener('system', appendSystem);
    },
    [serverId]);

    console.log("Rendering");
    console.log(messages);
}

The output I'm getting however...

Rendering
[]
Appending Permission granted. Attempting connection.
[]
Rendering
["Permission granted. Attempting connection."]
Appending Connection Succeeded
[]
Rendering
["Connection Succeeded"]

So it seems each time appendSystem is called, messages is an empty array. Therefore, setMessages is always appending the new message to an empty array.

Does anyone know what could be causing this? I'm under the impression appendSystem is for some reason caching 'messages' at the start, and reusing the original value, but have no idea how I would go about debugging or fixing that.

Upvotes: 0

Views: 104

Answers (1)

GalAbra
GalAbra

Reputation: 5138

This is a common issue with React hooks' non-intuitive state setting mechanism.

Try using setMessages with a function as its argument, rather than with the new value. This will guarantee you use its most recent value:

setMessages(prevMessages => [...prevMessages, message]);

Upvotes: 4

Related Questions