2

In a React app, I have this type of data:

const data = {
  open: [{
    id: 1,
    name: 'test 1'
  }, {
    id: 2,
    name: 'test 2'
  }],
  close: [{
    id: 3,
    name: 'test 3'
  }, {
    id: 4,
    name: 'test 4'
  }]
}

I want to iterate over each object in the open and close arrays and return the existing data with additional type field. E.g.:

const data = {
  open: [{
    id: 1,
    name: 'test 1',
    type: 'alert'
  }, {...],
  close: [...]
}

I'm trying something like this, but it returns undefined instead of the altered data:

const expandData = (data) => {
  return Object.keys(data).forEach((key) => {
    return data[key].map((item, idx) => ({
      ...item,
      type: 'alert'
    }))
  })
}

// call in another method
expandData(data) // the `data` above

https://jsfiddle.net/x5aspec2/

1
  • The reason it's returning undefined is because the code is returning the result of the forEach call, which will always be undefined. (forEach has side effects, but doesn't return anything). Commented Dec 4, 2017 at 13:36

8 Answers 8

2

You can use reduce() instead of forEach() and return object.

const data = {"open":[{"id":1,"name":"test 1"},{"id":2,"name":"test 2"}],"close":[{"id":3,"name":"test 3"},{"id":4,"name":"test 4"}]}

function expandData (data) {
  return Object.keys(data)
    .reduce((r, k) => {
      r[k] = data[k].map(o => ({...o, type: 'alert'}))
       return r;
    }, {})
}

const result = expandData(data)
console.log(result)

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

Comments

1

You can do

const data = {
  open: [{
    id: 1,
    name: 'test 1'
  }, {
    id: 2,
    name: 'test 2'
  }],
  close: [{
    id: 3,
    name: 'test 3'
  }, {
    id: 4,
    name: 'test 4'
  }]
}

function expandData (data) {
  return Object.keys(data).reduce((a, b) => {
    a[b] = data[b].map(e => ({
      ...e,
      type: 'alert'
    }))
    return a;
  }, {});
}

const result = expandData(data)
console.log(result)

1 Comment

it was the spread operator causing the error. I've checked "Use BabelJS / ES2015" in the snippet for you.
0

This approach can also be followed: If you need it smiple-

const data = {
  open: [{
    id: 1,
    name: 'test 1'
  }, {
    id: 2,
    name: 'test 2'
  }],
  close: [{
    id: 3,
    name: 'test 3'
  }, {
    id: 4,
    name: 'test 4'
  }]
}

function expandData (data) {
for(let key in data){
    if(data[key] instanceof Array){
    data[key].map(obj => {
    obj.type='alert'
  })
  }
}
return data
}

const result = expandData(data)
console.log(result)

https://jsfiddle.net/Lspd8345/2/

Comments

0

You could vreate new object and map the array objects with new property.

const
    expandData = data => 
        Object
            .keys(data)
            .map(key =>
                Object.assign(
                    { [key]: data[key].map(o => Object.assign({}, o, { type: 'alert' })) }
                )
            ),
    data = { open: [{ id: 1, name: 'test 1' }, { id: 2, name: 'test 2' }], close: [{ id: 3, name: 'test 3' }, { id: 4, name: 'test 4' }] };

console.log(expandData(data));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Comments

0

You just need to assign the new updated array from map to open and close properties instead of returning them.

Your whole code is correct and you need not change any method except that.

const expandData = (data) => {
  Object.keys(data).forEach((key) => {
    data[key] = data[key].map((item, idx) => ({
      ...item,
      type: 'alert'
    }))
  })
}

// call in another method
expandData(data);
console.log(data); //logs updated data

If your data is immutable than you can return a new object instead of modifying the same data object.

const expandData = (data) => {
  var result = {};
  Object.keys(data).forEach((key) => {
    result[key] = data[key].map((item, idx) => ({
      ...item,
      type: 'alert'
    }))
  })
 return result;
}
expandData(data);

5 Comments

that is returning the result of the forEach call, which will still be undefined.
Hi @SamHasler, it does not return the data but it updates the existing data. Please check it works fine
That's changing expandData from a function that returns a new object to one that mutates state. It's worth pointing that out because if someone wanted to have immutable data this wouldn't be suitable.
But it's not mentioned here that the data is immutable.
It doesn't say it's mutable either, so it's best to play it safe and not mutate it.
0

Try using this way, it works:

const data = {
  open: [{
    id: 1,
    name: 'test 1'
  }, {
    id: 2,
    name: 'test 2'
  }],
  close: [{
    id: 3,
    name: 'test 3'
  }, {
    id: 4,
    name: 'test 4'
  }]
}

function expandData (data) {
  let newObj = {}

    for(let key in data) {
        const objProp = data[key];
        newObj[key] = objProp.map((item, idx) => ({
              ...item,
              type: 'alert'
            }))
    }  

  return newObj;
}

const result = expandData(data)
console.log(result)

Comments

-1

Try using lodash with mapValues.

_.mapValues(data, element=>element.map(child=>{
    child.type = alert
    return child
}))

https://jsfiddle.net/x5aspec2/2/

Comments

-1

Your code is returning the result of the forEach call, which will always be undefined. (forEach has side effects, but doesn't return anything).

use map instead of forEach:

const data = { open: [{ id: 1,
                        name: 'test 1'
                      }, {
                        id: 2,
                        name: 'test 2'
                      }],
               close: [{id: 3,
                        name: 'test 3'
                      }, {
                        id: 4,
                        name: 'test 4'
                      }]
             };

const expandData = (data) => {
  return Object.keys(data).map((key) => { //<-- use map here instead of forEach
    return data[key].map((item, idx) => ({
      ...item,
      type: 'alert'
    }))
  })
}

document.write('<pre>'+JSON.stringify(expandData(data),null,2)+'</pre>')

Comments

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.