0

Assumption (based on tutorials and reading material): Example; https://redux.js.org/recipes/structuring-reducers/immutable-update-patterns

Updating an object property in an array best practice is through map versus foreach. Every example as per the redux breaks out map into two functions 1. Update object properties/s and return object. Even on medium and other expert content it follows this format

Example:

I'm iterating through an array of objects and updating every boolean active flag based on on whether that object's id property === id argument.

let items = [{id:1,active:false},{id:2,active:false},{id:3,active:false}];

const traditional = (items,id) => items.map(item => {
        item.active = item.id === id;
        return item
    })

console.log("traditional ", traditional(items, 3));
// outcome:  [{id:1,active:false},{id:2,active:false},{id:3,active:true}];

Question:

I've been using a combination of Object assign and map to condense the code, but I'm told that is bad practice and should stop. What am I missing i.e. what's the problem with this approach?

let items = [{id:1,active:false},{id:2,active:false},{id:3,active:false}];

const updateItemsById = (items,id) => items.map(item => Object.assign(item, {active:  (item.active = item.id === id)}))

console.log("update ", updateItemsById(items, 2));

2
  • 3
    I cannot see any good reason to use map instead of forEach if you do not need a new array. I see it as misleading. Commented Jun 8, 2021 at 5:50
  • Your .map() is still mutating each object. If your goal is to have a pure operation, then you can use Object.assign({}, item, {active: (item.active = item.id === id)}) - copy the object and overwrite active. Commented Jun 8, 2021 at 5:52

1 Answer 1

2

Updating an object property in an array best practice is through map versus foreach. Every example as per the redux breaks out map into two functions 1. Update object properties/s and return object. Even on medium and other expert content it follows this format

This is generally true only if you really need a separate array. Your current logic is mutating the existing objects, and returning a shallow copy of the array. This is quite an odd thing to do, and is probably the source of why some may be frowning on your existing approach. Usually, you'd want to create a whole new array with new objects, instead of mutating the existing array - use rest syntax instead of Object.assign to keep things more concise:

let items = [{id:1,active:false},{id:2,active:false},{id:3,active:false}];

const updateItemsById = (items,id) => items.map(item => ({
  ...item,
  active: item.id === id
}));

console.log("update ", updateItemsById(items, 2));

If you really intend to change the existing objects, then .map probably isn't appropriate - instead, use a generic iteration method like for or forEach, loop through the objects, and mutate them as needed. for and forEach loops are for generic side-effects.

let items = [{id:1,active:false},{id:2,active:false},{id:3,active:false}];

const traditional = (items,id) => {
  for (const item of items) item.active = item.id === id;
};

traditional(items, 3);
console.log("traditional ", items);

Sign up to request clarification or add additional context in comments.

6 Comments

Is there a reason for NOT using forEach in your second example? items.forEach(item => item.active = item.id === id); I find it much more concise
Other than no-return-assign (which most won't care about), not really, both methods work fine. I use for iterators instead of forEach just out of habit, not out of any more concrete reason.
The reason I asked is that OP specifically mentions Updating an object property in an array best practice is through map versus foreach which I disagree on due to the name and waste of an array, but have not investigated otherwise
@Nolan No. 2 possibilities I see here: (1) Mutate the objects - in which case, use generic iteration method like for or forEach. (2) From a functional perspective, create a new array with new objects. The only appropriate method when creating a new array that's one-to-one with an old array is Array#map. While you can use other array iteration methods to accomplish the same thing, .map makes the most sense by far, since the input and output items are one-to-one.
@Nolan accumulator.push(item) would just be re-writing .map as a .reduce. It's usually not a good solution, unless you're trying to generalise over other operations array like implementing a transducer. Normally, replacing .map with an equivalent .reduce doesn't make much sense.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.