2

I am trying to take an array of objects, check if the key exists in the array, and replace the value if the key exists, and if the key does not exist, I would like to add the key-value pair to the array. I thought it would be simple, but I am having trouble. The idea is to not have a situation where two objects with the same key exist in the array.

The array looks like...

let state = [{spouse: true}, {age: 50}, {numOfChildren: 2}, etc..]

My code is as such

const reducer = (state, action) => {
 switch(action.type){
    case "ADD_SPOUSE":
        // take state array
        // find the index of the object that has the correct key if it exists
        if (stateArrayHasObject) {
            // replace the current object {spouse: action.spouse} with the new value
            return state;
        } else {
            return ([...state, {spouse: action.spouse}]);
        }

In a truthy situation, how to I update the value of the object in the state array?

I checked this answer, this answer, and this answer, which don't really provide an efficient way of finding and replacing an object in an array if the object key exists in the array.

JayCodist
  • 2,424
  • 2
  • 12
  • 28
IWI
  • 1,528
  • 4
  • 27
  • 47
  • what is your expected output? – sonEtLumiere Aug 09 '20 at 23:55
  • 3
    It seems your life would be easier if you just had a flat object rather than an array of objects? I'm curious as to the reason for using that particular data structure? – Nick Aug 10 '20 at 00:26
  • @sonEtLumiere expected output is an array of objects that represents the state of the app, which is a form. in the form, each "question" will have an object that represents the "answer", i.e. the value – IWI Aug 10 '20 at 01:39
  • 1
    As @Nick said, why don't you just use an object? `state = {spouse: true, age: 50, numOfChildren: 2, etc..}`? Then: `state[somekey]==somevalue`. Simple enough, right? – iAmOren Aug 10 '20 at 01:51
  • @iAmOren that sounds simpler. ill switch over – IWI Aug 10 '20 at 14:56

2 Answers2

2

Iterate over the array with some. Check if the key from an object is equal to the searched key. If so than update the value for this object and return with true. by this the iteration over the array is stopped.
If by this any object with the searched key is founded create a new object with a property for this key (with the value) and push it to the array.

let state = [{spouse: true}, {age: 50}, {numOfChildren: 2}];

function updateKeyValue(state, key, value) {
    let found = state.some(obj => {
        if (Object.keys(obj)[0] === key) {
            obj[key] = value;
            return true;
        }
    });
    if (!found) {
        state.push( {[key]: value});
    }
    return state;
}

console.log(updateKeyValue(state,"age",48));
console.log(updateKeyValue(state,"help",'no'));
Sascha
  • 4,576
  • 3
  • 13
  • 34
1

You can map through the objects in the state array, use the in operator to check if property exists on the current object, and if so, return the affected object updated with new value

const reducer = (state, action) => {
 switch(action.type){
    case "ADD_SPOUSE":
       const key = "spouse";
       if (state.some(obj => key in obj) {
           return state.map(obj => key in obj ? {[key]: action[key]} : obj)
       }
       else {
           return [...state, {[key]: action[key]}]
       }
 ...
JayCodist
  • 2,424
  • 2
  • 12
  • 28