0

I have an array of objects in my state. I want to update the last object in array. But I don't want to explicitly mention the keys when updating the object.

This is how my code looks right now.

import React from 'react'
import update from 'immutability-helper'

class Container extends React.Component {
  state = { queue: [
    {title: 'title 1', message: 'message 1', dismissible: false},
    {title: 'title 2', message: 'message 2', dismissible: true},
    {title: 'title 3', message: 'message 3', dismissible: false},
  ] }
  updateLast = (contents) => {
    this.setState({
      queue: update(this.state.queue, {
        [this.state.queue.length-1]: {
          title: {$set: contents.title},
          message: {$set: contents.message},
          dismissible: {$set: contents.dismissible},
        },
      }),
    })
  }

  render() {
    return (
      <div className="notifications">
        {this.state.queue.map((notification, key) => (
          <Notification key={key} {...notification} />
        ))}
      </div>
    )
  }

As you can see, in the update method I am specifying the object keys title, message etc. explicitly. Is there some way I can update all the keys of the object using map or spread ... operator?

vikmalhotra
  • 9,981
  • 20
  • 97
  • 137
  • what do you mean by `keys`? Is that a property inside the `queue` object? – Arun AK Dec 31 '18 at 03:13
  • @Thinker `queue` is an array of objects. They keys are the object properties. I am updating my question with the contents of `queue`.. – vikmalhotra Dec 31 '18 at 03:29
  • @vikramalhotra may I know the reason of changing the key of the object? The key is a unique ID (from my understanding), so how you want to edit the key and why do you want to edit it? – Arun AK Dec 31 '18 at 03:33
  • @Thinker oh no. I don't want to change the keys. I want to update the values. But I don't want to use the keys explicitly to update the values. – vikmalhotra Dec 31 '18 at 03:37

2 Answers2

1

Using the spread operator, you could slice off the last item in the array and then create a new object to take its place like so:

updateLast = (contents) => {
  this.setState({
    queue: [...this.state.queue.slice(0, -1), {
      title: {$set: contents.title},
      message: {$set: contents.message},
      dismissible: {$set: contents.dismissible},
    }],
  })
}
kevin.groat
  • 1,274
  • 12
  • 21
1

If the contents object has the same shape as the items in your array, you could probably add in the object directly. You can remove the last index with .slice(0, -1), then use .concat to add the new item to the end. Also to make sure to use the callback form of setState, and always do so when the new state depends on the previous in some way.

this.setState((state) => ({
  queue: state.queue.slice(0, -1).concat(contents),
}))

Array spread works here as well.

this.setState((state) => ({
  queue: [...state.queue.slice(0, -1), contents],
}))
kingdaro
  • 11,528
  • 3
  • 34
  • 38