writingdeveloper
writingdeveloper

Reputation: 1076

How to modify array data with foreach

I took data from MongoDB and executed it with forEach statement.

However, I want to change the date data from 2018-08-01T00:00:00.000Z' to 'YYYY-MM.

When I ran console.log using the Moment package of Nodejs, the data I wanted was printed out.

console.log(moment(repo.created_at).format("YYYY-MM")) code normally outputs the data I want, but the original data did not change when saved as repo.created.

I don't know how to solve this problem.

/* GET MyPage Page */
router.get(`/:userId/admin/mypage`, function (req, res, next) {
  let userId = req.params.userId; // UserID Variable
  Repo.find({  // MongoDB
    'owner.login': userId
  }, function (err, repo) {
    if (err) throw err;
    // console.log(repo);
    repo.forEach(function (repo) {

     repo.created_at = moment(repo.created_at).format("YYYY-MM");
      console.log(repo.created_at)
      repo.updated_at = moment(repo.updated_at).format("YYYY-MM");
      console.log(repo.updated_at) 
    })
    res.render('mypage/main', {
      userId: userId,
      dataArray: repo,
    })
  })

When I console.log it it's still like this.

2018-08-01T00:00:00.000Z
2018-09-01T00:00:00.000Z
2018-09-01T00:00:00.000Z
2018-09-01T00:00:00.000Z
2018-09-01T00:00:00.000Z
2018-09-01T00:00:00.000Z
2018-08-01T00:00:00.000Z
2018-09-01T00:00:00.000Z
2017-08-01T00:00:00.000Z

But with console.log(moment(repo.created_at).format("YYYY-MM")) code. it works fine

2018-09
2018-09
2018-09
2018-09
2018-09
2018-09
2018-08

Upvotes: 1

Views: 634

Answers (3)

Helge Drews
Helge Drews

Reputation: 569

I recommend to use a map function instead of forEach, because it is normally more performant and doesn't mutate the original array. (A short demonstration about the differences between map and forEach is given in the article "JavaScript — Map vs. ForEach What’s the difference between Map and forEach in JavaScript?" at codeburst.io.)

Furthermore you should use a different name for your parameter names, because it can cause confusion about what is meant. This is called "scope" in JavaScript and it is also an example of "variable shadowing" or "name shadowing" and can cause subtle bugs. Therefor, you should use this with caution. In your case, you could name the loop parameter holding the array entries of your repo something like "repoElement", "repoItem", "repoEntry" or you find a more descriptive name.

You also say

but the original data did not change when saved as repo.created

If you do something like repoItem.created = moment(repoItem.created_at).format("YYYY-MM");, you add a new property to the repoItem-object, but the created_at property remains untouched. In the following example, I have named the formatted dates createdAt and updatedAt, so that these new properties get created. But every new repoItem will also have the untouched created_at and updated_at properties available next to the new properties createdAt and updatedAt.

// ...
const dataArray = repo.map(repoItem => ({
    ...repoItem,
    createdAt: moment(repoItem.created_at).format("YYYY-MM"),
    updatedAt: moment(repoItem.updated_at).format("YYYY-MM")
});
res.render('mypage/main', {
  userId,
  dataArray
})
// ...

If you don't want to include the originally formatted data, you have to make another step and destruct the data that you want before adding it to the new object. You can also destruct everything and then delete created_at and updated_at. This can be done like this:

const newRepoItem = { ...repoItem };
delete newRepoItem.created_at;
delete newRepoItem.updated_at;

or by using the "rest" parameter like this:

const { created_at, updated_at, ...newRepoItem } = repoItem;
// now, you can use the new variable newRepoItem.

More information about removing unwanted properties from an object can be found here: Remove value from object without mutation. I would use the version that is better understood by you and your team. In my opinion, the keyword delete is the solution that is easier to understand for most people, because it literally says what it does. But if you like destructuring and are used to it, this can be the more compact and readable solution. Don't forget, that it could also be possible, that you only have a few properties in your repoItem that you care about. In this case, you can simply destructure the items that you want to keep. This could look like in the following example:

// ...
const dataArray = repo.map(repoItem => {
    const { firstPropertyToKeep, secondPropertyToKeep } = repoItem;
    return ({
        firstPropertyToKeep,
        secondPropertyToKeep,
        createdAt: moment(repoItem.created_at).format("YYYY-MM"),
        updatedAt: moment(repoItem.updated_at).format("YYYY-MM")
    });
res.render('mypage/main', {
    userId,
    dataArray
})

I have create a REPL where you can see the difference between forEach and map: https://repl.it/@helgedrews/forEach-vs-map

I hope this helps a bit.

Upvotes: 1

Marcel Silvanus
Marcel Silvanus

Reputation: 54

Just use .map()

Example:

const updatedRepos = repos.map((repo)=>{
            return {
                ...repo,
                created_at: moment(repo.created_at).format("YYYY-MM");
                updated_at: moment(repo.updated_at).format("YYYY-MM");
            }
    })

Upvotes: 1

zkimyes
zkimyes

Reputation: 1

use [].map instead or set variable to save the result

Upvotes: 0

Related Questions