Irgend Son Hansel
Irgend Son Hansel

Reputation: 761

Vue, Vuex, JavaScript: includes() does not work as expected

I wanna store some objects inside an array if the array doesn't already contain some object with the same id. anyways, everything works fine til i start adding more than one object at a time.

Here is the related code using Vuex:

// filter function to check if element is already included
function checkForDuplicate(val) {
    for( let sessionItem of state.sessionExercises ) {
        return sessionItem._id.includes(val._id);
    }
};

// related array from vuex state.js
sessionExercises: [],


// vuex mutation to store exercises to session exercises
storeSessionExercises: (state, payload) => {
    // Pre filtering exercises and prevent duplicated content
    if( checkForDuplicate(payload) === true ) {
        console.log("Exercise ist bereits für session registriert!");
    } else {
        state.sessionExercises.push(payload);
    }
},


// Related vuex action
storeSessionExercises: ({ commit }, payload) => {
    commit("storeSessionExercises", payload)
},

As I wrote before everything works fine as long i ad a single object, checkForDuplicate() will find duplicated objects and deny a push to the array.

now there is a case in which I wanna push a bundle of objects to the array, which i am doing through an database request, looping through the output, extracting the objects and pushing them through the same function as I do with the single objects:

// get user related exercises from database + clear vuex storage + push db-data into vuex storage
addSessionWorkout: ({ commit, dispatch }, payload) => {
    axios.post(payload.apiURL + "/exercises/workout", payload.data, { headers: { Authorization: "Bearer " + payload.token } })
    .then((result) => {
        // loop through output array and 
        for( let exercise of result.data.exercises ) {
            // push (unshift) new exercise creation to userExercises array of vuex storage
            dispatch("storeSessionExercises", exercise)
        };
    })
    .catch((error) => {
        console.error(error)
    });
},

The push does also work as it should, the "filter function" on the other hand doesn't do its job. It will filter the first object and deny to push it to the array, but if there is a second one that one will be pushed to the array even inf the same object (same Id) is already included, what am I not seeing here!? makes me nuts! :D

I understand it like the loop will put each object through the checkForDuplicate() and look if there is an duplicate it should output true, so the object doesn't get pushed into the array. If anybody sees what I currently don't just let me know.

Upvotes: 1

Views: 1599

Answers (2)

aquilesb
aquilesb

Reputation: 2272

I would change the addSessionWorkout action, I would create a new exercises array with the old and new entries and then update the state.

// related array from vuex state.js
sessionExercises: [],


// vuex mutation to store exercises to session exercises
storeSessionExercises: (state, payload) => {
    state.sessionExercises = payload;
},


// Related vuex action
storeSessionExercises: ({ commit }, payload) => {
    commit("storeSessionExercises", payload)
},


addSessionWorkout: async({
  commit,
  dispatch,
  state
}, payload) => {
  const result = await axios.post(payload.apiURL + "/exercises/workout", payload.data, {
    headers: {
      Authorization: "Bearer " + payload.token
    }
  })

  try {
    const newExercices = result.data.exercises.reduce((acc, nextItem) => {
      const foundExcercise = acc.find(session => session.id === nextItem.id)
      if (!foundExcercise) {
        return [...acc, nextItem]
      }
      return acc
    }, state.sessionExercises)
    dispatch("storeSessionExercises", foundExcercise)
  } catch (e) {
    console.error(error)
  }
},

Upvotes: 0

oshell
oshell

Reputation: 9123

the mistake is your filter function. you want to loop over your sessionExercises and only return true if any of them matches. However, at the moment you return the result of the very first check. Your loop will always only run one single time.

Option 1: only return if matched

function checkForDuplicate(val) {
    for( let sessionItem of state.sessionExercises ) {
        if (sessionItem._id.includes(val._id)) {
            return true;
        }
    }
    return false;
};

Option 2: use es6 filter

storeSessionExercises: (state, payload) => {
    var exercises = state.sessionExercises.filter(ex => (ex._id.includes(payload._id)));
    if(exercises.length) {
        console.log("Exercise ist bereits für session registriert!");
    } else {
        state.sessionExercises.push(payload);
    }
}

Upvotes: 2

Related Questions