reef
reef

Reputation: 147

Add key/value pair to existing array of objects

I have an array of objects that is saved into a userList useState which is composed of:

[{
    firstName: "blah" 
    lastName: "blah2"
 }

 {
    firstName: "test"
    lastName: "test2"
}]

I have a useEffect that calls a function and returns a value. I want to store a new key and value to each user in userList.

useEffect(() => {

        userList.forEach((user, index) =>
            returnNewValueForNewKeyFunction(user, index).then(newValue => {

                userList[index]['newKey'] = newValue
                //this console.log shows new field and value
                console.log(userList)
                //this console.log ALSO shows new field and value
                console.log(JSON.stringify(contactList[index]))
            })
        )
    }
}, [])

This is fine if I'm operating out of console.log, but unfortunately I need to render the data onto the page.. in my render I have:

return (
    <TableBody>
        {userList
            .map((user, index) => (
                 <TableRow>
                     <TableCell>
                         {user.newKey}
                     </TableCell>
)

user.newKey is showing as blank and it seems like the user wasn't updated at all. How can I make it so the value is actually updated and can be read from when rendering?

Upvotes: 0

Views: 4388

Answers (2)

smashed-potatoes
smashed-potatoes

Reputation: 2222

You are modifying your userList but not calling your set function on which means React won't know to re-render with the updated state.

Instead of mutating the current state, you should create a new array and then call the set function returned by useState with the updated array after making your changes.

It also looks like your returnNewValueForNewKeyFunction is a promise / async which means each of your item changes are happening async. You'll need to make these synchronous / wait for them all before updating your state to make your state change a single update for the UI.

E.g., putting these both together - if you are doing:

const [userList, setUserList] = useState();

You could do:

useEffect(() => {
    // Since can't use an async func directly with useEffect -
    // define an async func to handle your updates and call it within the useEffect func
    const updateUsers = async () => {
        // Create a new array for your updated state
        const updatedUserList = [];

        // Loop over your values inline so your can await results to make them sync
        for (let index = 0; index < userList.length; index ++) {
            const user = userList[index];
            const newVal = await returnNewValueForNewKeyFunction(user, index);

            // Create a shallow copy of the original value and add the newValue
            updatedUserList[index] = { ...user, newKey: newValue };
            // ... Any other logic you need
        }

        // Call set with the updated value so React knows to re-render
        setUserList(updatedUserList);
    };

    // Trigger your async update
    updateUsers();
}, [])

Upvotes: 0

Morphex
Morphex

Reputation: 306

You shouldnt mutate your list, you should use useState to store your list, so something like this :

const [ state, setState] = useState(userList);

Then when you want to update, do something like this :

const listCopy = [...state];
//Logic to update your list here
listCopy[index][otherindex] = Value;
setState(listCopy)

Hope this helps

Upvotes: 2

Related Questions