0

I have a table with data:

enter image description here When i click on remove button I know index and userID who have this data. I would like to remove this object from "timeRecords" array and return "employeeList" without it.

enter image description here

I tried implemented this function, but without result

//recordId = index and key also, userID = userId who have this records.
  deleteRecord = (recordID, userID) => {  
    console.log(`usunięto rekord: ${recordID}, na użytkowniku o ID: ${userID}`);
    let employeesList = this.state.employeesList;
    employeesList = employeesList.filter(el => {
      if (el.id === userID) {
        if (el.timeRecords !== recordID) {
          return el.timeRecords;
        }
      }
    });
  };
2
  • Could you please add the input array and which object is required to be removed? Commented Jul 10, 2019 at 17:43
  • I have 2 inputs: input time and number. Value from inputs are connect with state, when you click on the button "add", then you create a object {id: 0, day: '2019-01-01' hours: 8'} next is for example: {id:1, etc.}. Which object must be removed is dependent on what you clicked. Main object "employeeList" is the same but with different data Commented Jul 10, 2019 at 18:06

3 Answers 3

2

You can use a .map() and a nested .filter() like this to remove the identified object. The .map() is used to iterate over employee objects. Once an employee with a matching id is found, we then iterate over their timeRecords to filter out the one we want to remove:

deleteRecords = (recordId, userId) => {
  const { employeesList } = this.state
  const newArr = employeesList.map((item) => {
    if(item.id == userId){
        return {
            ...item,
            timeRecords: item.timeRecords.filter((record) => record.id !== recordId)
        }
    } else {
        return item
    }
  })
}

Run example below:

var array = [{id: 1, timeRecords: [{id: 5, hours: 2}, {id: 6, hours: 3}]}, {id: 2, timeRecords: [{id: 7, hours: 2}, {id: 8, hours: 3}]}]

const deleteRecords = (recordId, userId) => {
  const newArr = array.map((item) => {
    if(item.id == userId){
        return {
            ...item,
            timeRecords: item.timeRecords.filter((record) => record.id !== recordId)
        }
    } else {
        return item
    }
  })
  
  console.log(newArr)
}

deleteRecords(5, 1)

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

10 Comments

@vicbyte two reasons. 1) To create a new copy of the employeeList. 2) It makes it easier to identify the employee who's timesheet we remove since we iterate over each employee. I contemplated on just using .filter() -> .filter() at first but I don't think the logic would be as clean.
@vicbyte its a very React specific issue that requires a brand new copy of an array when updating state. If we were to do any mutations on an existing state-value (ie: the employeesList) without first creating a new array, it could lead to some unintended side-effects. Although I get what you mean, why use the extra space and memory xD
Actually, we don't need a new array variable here. It is the same thing returning mapped employees or creating a new one. Since, we do no mutate state directly in map callback. We are filtering the timerecords and returning a new employee with new time record using spread syntax. Also, map just creates shallow copies :)
Guys thanks for the help, but now is another problem, I see the result on console.log but no on the website, If I want to see the result I must move to other URL and back.
Did you ever update the state with the newArr? @Vuzii
|
0
[{
  accountNumber: "1111111",
  id: 1,
  timeRecords: [{
    id: 0,
    hours: '1'
  }, {
    id: 1,
    hours: '2'
  }, {
    id: 2,
    hours: '3'
  }]
}]

solution, might look over-engineered, but this is the correct way to mutate

deleteRecord = (recordID, userID) => {  
    const list = this.state.employeesList;
    const index = list(v => v.id === userID)
    const nestedList = list[index].timeRecords
    const nestedIndex = nestedList.findIndex(v => v.id === recordID)
    return [
      ...list.slice(0, index), // get items before the userID
      {
        ...list[index], // fill other pros of userID
        timeRecords: [ // remove item by recordID
          ...nestedList.slice(0, nestedIndex),
          ...nestedList.slice(nestedIndex + 1)
        ]
      },
      ...list.slice(index + 1) // get items after the userID
    ]
  }

Comments

0

So, you want to remove a specific timerecord from a specific user right? You can map users, if id is not a match you can turn this user immediately, if they match then you can filter timerecords and update the user with this.

deleteRecord = (recordID, userID) => {
  return employeesList.map(employee => {
    if (employee.id !== userID) return employee;

    const timeRecords = employee.timeRecords.filter(
      timeRecord => timeRecord.id !== recordID
    );

    return { ...employee, timeRecords };
  });
};

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.