0

I'm trying to remove an item from a childArray that is nested into another Array.

This is How I'm trying.

const childArrayHandler = (childData, sub, questionId, data, btnId) => {
    // Manage color change on click
    const isInList = selectedBtnList.some((item) => item === btnId)
    if (isInList) {
      onSelectedBtnListChange(selectedBtnList.filter((item) => item !== btnId))
    } else {
      onSelectedBtnListChange([...selectedBtnList, btnId])
    }

    // Manage childData Array 
    // copy data to mutable object
    const currentChildData = [...childData]
    const hasId = currentChildData.find(({ id }) => sub.id === id)

    if (!hasId) {
      // add item to childArray if same index is not available in the childArray
      const newChild = { id: sub.id, sub_question: sub.sub_question, weightage: sub.weightage }
      currentChildData.push(newChild)
      setChildDataOnChange((current) => [...current, newChild])
    } else if (hasId) {
      // remove item from childArray if same index is available in the childArray
      const indexOfChild = currentChildData.indexOf(hasId)
      // console.log('currentChildData', currentChildData, 'indexOfChild', indexOfChild)
      currentChildData.slice(indexOfChild, 1)
      setChildDataOnChange(currentChildData)
    }

    const newData = [...data]

    // find parent of the child
    const parent = newData.find(({ parentId }) => questionId === parentId)

    // find index of parent
    const indexOfParent = newData.indexOf(parent)
    // update data with child related to parent
    newData[indexOfParent].child = currentChildData
    onDataChange(newData)
    localStorage.setItem('deviceReport', JSON.stringify(newData))
  }

The problem is in the else if block, I want if there's an index of object available in the child then it should remove it from the array. As far as I can see I'm using the correct approach as other articles suggested to handle but missing something which I cant see right now. But not able to find the proper result. If I console it doesn't change anything. means don't remove any item from the array if the index is already is there.

So how can I fix this, or what might be doing wrong, is there any other way to do it please also mention it? Thanks

14
  • console.log('currentChildData', currentChildData, 'indexOfChild', indexOfChild) which value did you get here? Commented Apr 5, 2022 at 9:02
  • I get expected results like currentChildData (2) [{…}, {…}] indexOfChild 0 Commented Apr 5, 2022 at 9:06
  • you have expected currentChildData, but setChildDataOnChange(currentChildData) does not affect? Commented Apr 5, 2022 at 9:08
  • 1
    A) It is unnecessary for else if (hasId) when the previous condition is if (!hasId). If hasId is falsy, the if would have executed. No need to again check. B) At this line: currentChildData.slice(indexOfChild, 1) - you expect currentChildData to be changed, right? Please read documentation for .slice() method. Does it mutate the array? Hint: The last statement in the first-paragraph: The original array will not be modified. Commented Apr 5, 2022 at 9:18
  • 2
    @jsN00b I think it has some hidden changes behind this. I was trying to guess around those changes without running code, but you're right about that slice is the problem in this piece of code Commented Apr 5, 2022 at 9:47

1 Answer 1

3

You have the problem with this slice

currentChildData.slice(indexOfChild, 1)

It does not initialize a new array for you (React's immutability)

The fix could be

currentChildData = currentChildData.slice(0, indexOfChild).concat(currentChildData.slice(indexOfChild + 1))

If you feel it's too complicating, you can use filter instead

currentChildData = currentChildData.filter((item) => item !== hasId) //`hasId` is your found item with `find`

The 2nd problem here is

newData[indexOfParent].child = currentChildData

You cannot assign a value to a mutate object

The proper way should be

newData = newData.map((item) => item === parent ? {...item, child: currentChildData} : item)

The full code

const childArrayHandler = (childData, sub, questionId, data, btnId) => {
    // Manage color change on click
    const isInList = selectedBtnList.some((item) => item === btnId)
    if (isInList) {
      onSelectedBtnListChange(selectedBtnList.filter((item) => item !== btnId))
    } else {
      onSelectedBtnListChange([...selectedBtnList, btnId])
    }

    // Manage childData Array 
    // copy data to mutable object
    let currentChildData = [...childData]
    const hasId = currentChildData.find(({ id }) => sub.id === id)

    if (!hasId) {
      // add item to childArray if same index is not available in the childArray
      const newChild = { id: sub.id, sub_question: sub.sub_question, weightage: sub.weightage }
      currentChildData.push(newChild)
      setChildDataOnChange((current) => [...current, newChild])
    } else  {
      // console.log('currentChildData', currentChildData, 'indexOfChild', indexOfChild)
      currentChildData = currentChildData.filter((item) => item !== hasId)
      setChildDataOnChange(currentChildData)
    }

    //let newData = [...data]

    // find parent of the child
    //const parent = newData.find(({ parentId }) => questionId === parentId)

    // update data with child related to parent
    //newData = newData.map((item) => item === parent ? {...item, child: currentChildData} : item)

    //shorter version
    const newData = data.map((item) => item.parentId === questionId ? {...item, child: currentChildData} : item)
    
    onDataChange(newData)
    localStorage.setItem('deviceReport', JSON.stringify(newData))
  }
Sign up to request clarification or add additional context in comments.

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.