1

I have an array of objects saved in state and each of the objects in the array has another array on objects.

here is an example of a single object:

            id       : uuid.v1(),
            area     : 'Scratch',
            name     : 'Untitled',
            status   : "",
            size     : "",
            created  : {
                name : "username",
                time : new Date()
            },
            modified : {
                name : "username",
                time : new Date()
            },
            content: [{
                id        : uuid.v1(),
                Content   : "Content 1",
                TowerRed  : "",
                TowerText : "text"
            },
            {
                id        : uuid.v1(),
                Content   : "Content 2",
                TowerRed  : "",
                TowerText : "text"
            }]

I need to be able to remove an object from inside the content array inside of these objects.

For example I need to remove the object containing 'content 1' without modifying the object containing 'content 2'

I have tried to use the react immutability helpers her but with no success.

here I loop through the parent objects and the content objects until I find a match with the 'itemID' (itemID) is the id of the object i want to remove form the content array.

     var tickerIndex = null;
        var tickerItemIndex = null;

        for (var i = 0; i < this.state.scratchTickers.length; i++) {

            var tickersContent = this.state.scratchTickers[i].content;
            tickerIndex = i;

            for (var x = 0; x < tickersContent.length; x++) {
                if (tickersContent[x].id == itemID) {                   
                    tickerItemIndex = x;
                }           
            }
        }

then I create a reference to the parent object and its content array:

var item = this.state.scratchTickers[tickerIndex].content;

Finally I use the update immuatbility help to splice the array and remove the correct object based on its itemID:

this.setState ({
        scratchTickers: update(item, {
            $splice: [[tickerItemIndex, 1]]
        })
    })

But this just doesn't seem to work.

here is the whole function:

_deleteTickerItem: function(itemID) {
        var tickerIndex = null;
        var tickerItemIndex = null;

        for (var i = 0; i < this.state.scratchTickers.length; i++) {

            var tickersContent = this.state.scratchTickers[i].content;
            tickerIndex = i;

            for (var x = 0; x < tickersContent.length; x++) {
                if (tickersContent[x].id == itemID) {                   
                    tickerItemIndex = x;
                }           
            }
        }

        var item = this.state.scratchTickers[tickerIndex].content;

        this.setState ({
            scratchTickers: update(item, {
                $splice: [[tickerItemIndex, 1]]
            })
        })

    },
chinds
  • 1,761
  • 4
  • 28
  • 54
  • You could use lodash's _.reject() method object.content = _.reject(object.content, {Content: 'Content 1'}); – baao Feb 17 '16 at 11:44
  • @Michael Thanks for the suggestion, I now have the _.reject() function work, any idea how I would then push that object into the array of objects held in state? `var item = this.state.scratchTickers[tickerIndex].content; item = _.reject(item, {id: itemID});` – chinds Feb 17 '16 at 13:28

1 Answers1

1

It looks like your setState call is overriding your scratchTickers data with just the value of one particular scratchTicker's content.

What you're essentially trying to do is map your array of scratchTickers to a new array with filtered content.

_deleteTickerItem: function(itemID) {
  this.setState({
    scratchTickers: this.state.scratchTickers.map(scratchTicker =>
      Object.assign({}, scratchTicker, {
        content: scratchTicker.content.filter(content => content.id != itemID)
      })
    )
  });
}

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

Update:

When rendering, make sure if you're using an iterator that you're not using the array indices as keys, like this.

// bad
{content.map((content, index) =>
  <p key={index}>{content.Content}</p>
)}

When React diffs with the virtual DOM on a change, it will look at the keys to determine what has changed. So if you're using indices and there is one less in the array, it will remove the last one. Instead, use the id's of the content as keys, like this.

// good
{content.map(content =>
  <p key={content.id}>{content.Content}</p>
)}
Adam Particka
  • 604
  • 6
  • 4
  • Hi, Thanks for the info, this works in the fact that items are being deleted, however it just seems to delete the last object in the array not the specified object – chinds Feb 17 '16 at 15:49
  • Hmm, I made a JSBin here that seems to work correctly. http://jsbin.com/qirizuw/edit?js,console – Adam Particka Feb 17 '16 at 16:13
  • ahh i think that is my issue, as I removed the setting of state and just console.logged the result and it is intact removing the correct object. – chinds Feb 17 '16 at 16:48