Antonio Pavicevac-Ortiz
Antonio Pavicevac-Ortiz

Reputation: 7729

React hooks: useState, Updater function nested in for loop not updating state

I have a useEffect hook where I'm splitting a string from state by line break to create an array,

That array is being looped over and what I'd like is to either add an object to my state/hook (messageContainer) with and id and a message property e.g {id: i, message: messageRow[i]} if it doesn't exist or update it if it exists e.g return {...messageObj, message: messageRow[i]}

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

const [messagesContainer, setMessagesContainer] = useState([])

useEffect(() => {
var messageRow = messages.split('\n');

for (let i = 0; i < messageRow.length; i++) {
    setMessagesContainer(previousState => (
        [...previousState,
            ...previousState.map((messageObj, index, arr) => {
                if (messageObj.id === i) {
                    return {
                        ...messageObj,
                        message: messageRow[i]
                    }
                } else {
                    return {
                        id: i,
                        message: messageRow[i]
                    }
                }
            })
        ]
    ))
}
}, [messages])

messagesContainer is coming back empty?

How do I update the array if it has a object with the property or add it if it doesn't yet exist?

Thank you in advance!

Update:

As Bart mentioned below, I should be initializing messageContainer

SO I did:

const [messagesContainer, setMessagesContainer] = useState([{id: 0, messages: null}])

But now it just appends to the array and not update the same object:

enter image description here

Upvotes: 2

Views: 337

Answers (1)

Vrushali Bhosale
Vrushali Bhosale

Reputation: 98

Try something like the below code in useEffect. It will work.

useEffect(() => {
var messageRow = messages.split("\n");
let allMessages = [...messagesContainer]
for (let i = 0; i < messageRow.length; i++) {
  let match = allMessages.filter(item=>item.id===i);
  if(match?.length){
    match[0].messages=messageRow[i];
  }
  else{
    allMessages.push({id:i,messages:messageRow[i]})
  }
}
console.log(allMessages);
setMessagesContainer(allMessages);
}, [messages]);

Upvotes: 1

Related Questions