javascriptnode.jsreactjsreduxredux-reducers

How can i correctly use filter and map in the reducers folder for the workouts objects?


I am trying to make the correct delete and update requests for the workout object an I get an error that says the filter is not a function as I am using it on an object and not on an array. Below is the code that I am using for the reducers.

import { FETCH_ALL, CREATE, UPDATE, DELETE, LIKE, COMMENT_WORKOUT } from '../constants/actionTypes';

export default (workouts=[],action)=>{
   switch(action.type){
    case FETCH_ALL:
        return action.payload;
    case CREATE:
        return [...workouts, action.payload];
    case UPDATE:
        return workouts.map((workout) => (workout._id === action.payload._id ? action.payload : workout));
    case LIKE:
        return workouts.map((workout) => (workout._id === action.payload._id ? action.payload : workout));
    case DELETE:
        return workouts.filter((workout) => workout._id !== action.payload);
    case COMMENT_WORKOUT:
        return workouts.map((workout) => (workout._id === action.payload._id ? action.payload : workout));
    default:
        return workouts;
   }
}

Below I have the code for my actions folder with the requests I make:

import { FETCH_ALL, CREATE, UPDATE, DELETE, LIKE, COMMENT_WORKOUT, COMMENT_MEAL } from '../constants/actionTypes';

import * as api from '../api';

export const getWorkouts=()=> async (dispatch)=>{
    try{
        const data=await api.fetchWorkouts();

        dispatch({type:FETCH_ALL,payload:data});
        console.log(data);
    }catch(error){
        console.log(error);
    }

}

export const getWorkoutsBySearch=(searchQuery)=>async(dispatch)=>{
    try{
        const {data:{data}}=await api.fetchWorkoutsBySearch(searchQuery);

        console.log(data);
    }catch(error){
        console.log(error);
    }
}

export const createWorkout=(workout)=>async(dispatch)=>{
    try{
            const data=await api.createWorkout(workout);

            dispatch({type:CREATE,payload:data});
            console.log(data);
    }catch(error){
            console.log(error.message);
    }
}

export const updateWorkout=(id,workout)=>async(dispatch)=>{
    try{
        const data=await api.updateWorkout(id,workout);

        dispatch({type:UPDATE,payload:data})
    }catch(error){
        console.log(error);
    }
}

export const deleteWorkout = (id) => async (dispatch) => {
    try {
      await api.deleteWorkout(id);
  
      dispatch({ type: DELETE, payload: id });
    
    } catch (error) {
      console.log(error);
    }
  };

export const likeWorkout=(id)=>async(dispatch)=>{
    try{
        const data=await api.likeWorkout(id);
        console.log(data)
        dispatch({type:LIKE,payload:data})
    }catch(error){
        console.log(error);
    }
}

export const postCommentOnWorkout=(data)=>async(dispatch)=>{
    try{
        const res=await api.postCommentOnWorkout(data);
        dispatch({type:COMMENT_WORKOUT,payload:res})
    }catch(error){
        console.log(error);
    }
}

export const postCommentOnMeal=(data)=>async(dispatch)=>{
    try{
        const res=await api.postCommentOnMeal(data);
        dispatch({type:COMMENT_MEAL,payload:res})
    }catch(error){
        console.log(error);
    }
}

What should I change? I get also the same error for the map function that I use in the update. Thanks!


Solution

  • Since your action.payload is an object when the case is 'FETCH_ALL', your state becomes an object and you are not able to use array methods. Convert your object into an array, then return it.

    export default (workouts = [], action) {
      switch (action.type) {
        case 'FETCH_ALL': {
          const allWorkouts = []
          const ids = Object.keys(action.payload)
    
          for (let i = 0; i < ids.length; i++) {
             allWorkouts.push(action.payload[ids[i]])
          }
    
          return allWorkouts 
        }
      }
    }