Home > Net >  how to properly update an array of Object in javascript/React
how to properly update an array of Object in javascript/React

Time:11-23

I have here a map function for an array of object and also added some condition

 userList.map((item) => {
  const newFilter = dailyData.filter((value) => {
    return value.author == item.MSM;
  });

  let obj_idx = userList.findIndex(
    (obj) => obj.MSM == newFilter[0]?.author
  );

  const newArr = userList?.map((obj, idx) => {
    if (idx == obj_idx) {
      return {
        ...obj,
        storeTimeIn: newFilter[0]?.store,
        timeIn: newFilter[0]?.date_posted,
        storeTimeOut: newFilter[newFilter.length - 1]?.store,
        timeOut: newFilter[newFilter.length - 1]?.date_posted,
      };
    } else {
      return obj;
    }
  });

  console.log(newArr);
  setAttendanceData(newArr);
});

that just check if the Item exist in the array before updating it.

and this condition here works fine

if (idx == obj_idx) {
          return {
            ...obj,
            storeTimeIn: newFilter[0]?.store,
            timeIn: newFilter[0]?.date_posted,
            storeTimeOut: newFilter[newFilter.length - 1]?.store,
            timeOut: newFilter[newFilter.length - 1]?.date_posted,
          };
        }

enter image description here

as seen in this picture

but when my condition becomes false the whole array of object becomes empty again

enter image description here

my hunch is I'm setting the state wrongly . which appear in the setAttendanceData(newArr) this state is just an empty array state const [attendanceData, setAttendanceData] = useState([]);. is there a way to not update the whole array of object when the condition gets false like how can I use spread operator in this situation. TIA

CodePudding user response:

I feel you need to add a little more description including the current react component and little bit about your inputs/outputs for a more refined answer.

userList.map((item, index, self) => {
  const newFilter = dailyData.find((value) => {
    return value.author === item.MSM;
  });

  // this is only needed if there can be multiple 
  // occurrence of same obj.MSM in 'userList' array
  let obj_idx = self.findIndex((obj) => obj.MSM === newFilter[0] ? .author);

  // why are you doing this
  const newArr = self ? .map((obj, idx) => {
    if (idx == obj_idx) {
      return {
        ...obj,
        storeTimeIn: newFilter[0] ? .store,
        timeIn: newFilter[0] ? .date_posted,
        storeTimeOut: newFilter[newFilter.length - 1] ? .store,
        timeOut: newFilter[newFilter.length - 1] ? .date_posted,
      };
    } else {
      return obj;
    }
  });

  console.log(newArr);
  // why are you doing this , updating state on every iteration
  // after user.map attendanceData will only reflect for the last index in userList
  setAttendanceData(newArr);
});

But if my assumptions are correct, this following code snippet may help you in some way.

setAttendanceData(
  // make sure to run setAttendanceData only once
  userList.map((item, index, self) => {
    const newFilter = dailyData.find((value) => {
      return value.author === item.MSM;
    });

    const obj_idx = self.findIndex((obj) => obj.MSM === newFilter[0] ? .author);

    // there can be refinement around this but i feel this is what you need
    if (index === obj_idx) {
      return {
        ...obj,
        storeTimeIn: newFilter[0] ? .store,
        timeIn: newFilter[0] ? .date_posted,
        storeTimeOut: newFilter[newFilter.length - 1] ? .store,
        timeOut: newFilter[newFilter.length - 1] ? .date_posted,
      };
    } else {
      return obj;
    }
  })
);

CodePudding user response:

First, I would re-examine this logic. You're calling map inside of map on the same array, which is confusing. The top level map is used more like a forEach than a map because nothing is done with the output. You're also updating state on each iteration of the loop. I'm not sure how React handles this situation.

Try to only set state once the data is in the shape you want. Ideally it would only require one pass through the array. Here is an example:

  const [attendanceData, setAttendanceData] = useState([]);
  const [userList, setUserList] = useState([
    { MSM: "Edmond" },
    { MSM: "Dantes" },
    { MSM: "Conan" },
  ]);
  const [dailyData, setDailyData] = useState([
    { author: "No one", store: "store", date_posted: "a date" },
    { author: "Edmond", store: "store", date_posted: "a date" },
    { author: "Conan", store: "store", date_posted: "a date" },
  ]);

  useEffect(() => {
    const mappedUserList = userList.map((user) => {
      // Find the daily data author that matches the current user.
      const day = dailyData.find((value) => {
        return value.author == user.MSM;
      });

      if (!day) {
        // If no author matched in daily data, return the user unchanged.
        return user;
      } else {
        return {
          ...user,
          storeTimeIn: day.store,
          timeIn: day.date_posted,
          // I'll leave these lines for you to figure out
          // since I don't understand why you're getting the last element of the filtered data.
          // storeTimeOut: filteredDailyData[filteredDailyData.length - 1]?.store,
          // timeOut: filteredDailyData[filteredDailyData.length - 1]?.date_posted,
        };
      }
    });

    setAttendanceData(mappedUserList);
  }, [userList, dailyData]);

  console.log(attendanceData);
  • Related