TypeError: state is not iterable on React

39 Views Asked by At

I created a mern app that allows you to add workouts and meals to the app, it is allowing me to create and upload the workouts but the meals throws:

state.meals is not iterable
TypeError: state.meals is not iterable
    at mealsReducer (http://localhost:3000/static/js/bundle.js:1114:42)
    at updateReducer (http://localhost:3000/static/js/bundle.js:29477:26)
    at Object.useReducer (http://localhost:3000/static/js/bundle.js:30544:20)
    at useReducer (http://localhost:3000/static/js/bundle.js:46654:25)
    at MealsContextProvider (http://localhost:3000/static/js/bundle.js:1128:78)
    at renderWithHooks (http://localhost:3000/static/js/bundle.js:29168:22)
    at updateFunctionComponent (http://localhost:3000/static/js/bundle.js:32050:24)
    at beginWork (http://localhost:3000/static/js/bundle.js:33762:20)
    at HTMLUnknownElement.callCallback (http://localhost:3000/static/js/bundle.js:18760:18)
    at Object.invokeGuardedCallbackDev (http://localhost:3000/static/js/bundle.js:18804:20)

I have tried to do the WorkoutContext code into this but replacing it to meals but still doesn't work.

The console logs this:

react-dom.development.js:18687 The above error occurred in the <MealsContextProvider> component:

    at MealsContextProvider (http://localhost:3000/static/js/bundle.js:1125:3)
    at WorkoutsContextProvider (http://localhost:3000/static/js/bundle.js:1224:3)
    at AuthContextProvider (http://localhost:3000/static/js/bundle.js:1016:3)

Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.

The code in my MealContext.jsx is:

import { createContext, useReducer } from "react";

export const MealsContext = createContext()

export const mealsReducer = (state, action) => {
   switch (action.type) {
       case 'SET_MEALS':
           return {
               meals: action.payload
           }
       case 'CREATE_MEAL':
           return {
               meals: [action.payload, ...state.meals]
           }
       case 'DELETE_MEAL':
           return {
               meals: state.meals.filter((w) => w._id !== action.payload._id)
           }
       default:
           return state
   }
}

export const MealsContextProvider = ({ children }) => {
   const [state, dispatch] = useReducer(mealsReducer, {
       meals: null
   })

   return (
       <MealsContext.Provider value={{ ...state, dispatch }}>
           {children}
       </MealsContext.Provider>
   )
}     }
       case 'CREATE_MEAL':
           return {
               meals: [action.payload, ...state.meals]
           }
       case 'DELETE_MEAL':
           return {
               meals: state.meals.filter((w) => w._id !== action.payload._id)
           }
       default:
           return state
   }
}

export const MealsContextProvider = ({ children }) => {
   const [state, dispatch] = useReducer(mealsReducer, {
       meals: null
   })

   return (
       <MealsContext.Provider value={{ ...state, dispatch }}>
           {children}
       </MealsContext.Provider>
   )
}
1

There are 1 best solutions below

0
Nicholas Tower On
case 'CREATE_MEAL':
  return {
    meals: [action.payload, ...state.meals]
  }

state.meals starts off as null, and so ...state.meals throws the error you're seeing. You either need to handle the possibility that it's null:

return {
  meals: state.meals ? [action.payload, ...state.meals] : [action.payload]
}

Or make meals always be an array:

const [state, dispatch] = useReducer(mealsReducer, {
  meals: []
})