Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Uncaught TypeError: Cannot read properties of undefined (reading 'map') React

So im following this tutorial and im struggling with the following step. Redux was introduced and it not working. I googled the error that I found in the developer Tool and I still couldn’t fix the error by trying many proposed solutions. The error is in HomeScreen in line 25 (products.map) My code:

HomeScreen.js:

import React, {useState, useEffect} from 'react'
import {Row, Col} from 'react-bootstrap'
import Product from '../components/Product'
import { useDispatch, useSelector} from 'react-redux'
import {listProducts} from '../actions/productActions'


function HomeScreen() {

    const dispatch = useDispatch()
    const productList = useSelector(state => state.productList)
    const {error, loading, products} = productList

    useEffect(() =>{
        dispatch(listProducts())
    },[dispatch])
    
  return (
    
        <div>
            <h1>Latest Products</h1>
            {loading ? <h2>Loading..</h2>
                : error ? <h3>{error}</h3>
                :
                <Row>
                {products.map(product => (
                    <Col key={product._id} sm={8} md={6} lg={4} xl={2}>
                        <Product product={product} />
                    </Col>
                ))}
                </Row>
            }
            
        </div>
    
  )
}

store.js:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

import { legacy_createStore as createStore, combineReducers, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import { composeWithDevTools } from 'redux-devtools-extension'
import {productListReducer} from './reducers/productReducers'


const reducer = combineReducers({
    productList: productListReducer,
})
const initialState = {}
const middleware = [thunk]
const store = createStore(reducer, initialState, 
    composeWithDevTools(applyMiddleware(...middleware)))

export default store

productActions.js:

import axios from 'axios'
import {PRODUCT_LIST_REQUEST,PRODUCT_LIST_SUCCESS,PRODUCT_LIST_FAIL} from '../constants/productConstants'

export const listProducts = () =>  async(dispatch) => {
    try {
        dispatch({type: PRODUCT_LIST_REQUEST})

        const {data} =  await axios.get('/api/products/')

        dispatch({
            type: PRODUCT_LIST_SUCCESS,
            payload: data
        })
    } catch (error) {
        dispatch({
            type: PRODUCT_LIST_FAIL,
            payload: error.response && error.response.data.message
            ? error.response.data.message
            : error.message, 
        })
    }
}

productReducers.js

import {
    PRODUCT_LIST_REQUEST,
    PRODUCT_LIST_SUCCESS,
    PRODUCT_LIST_FAIL
} from '../constants/productConstants'


export const productListReducer = (state={products:[]},action) => {
    switch(action.type){
        case PRODUCT_LIST_REQUEST:
            return {loading:true, product:[]}

        case PRODUCT_LIST_SUCCESS:
            return {loading:false, product:action.payload}

        case PRODUCT_LIST_FAIL:
            return {loading:false, error: action.payload}
        
        default:
            return state
    }
}

>Solution :

You should consistently name the state. The state is initially named products, but all the case reducers replace it with product. Don’t forget to also always shallow copy the previous state object into the next state object.

export const productListReducer = (state={ products: [] }, action) => {
  switch(action.type) {
    case PRODUCT_LIST_REQUEST:
      return {
        ...state,
        loading: true,
        products: [],
      };

    case PRODUCT_LIST_SUCCESS:
      return {
        ...state,
        loading: false,
        products: action.payload,
        error: null,
      };

    case PRODUCT_LIST_FAIL:
      return {
        ...state,
        loading: false,
        error: action.payload,
      };
    
    default:
      return state;
  }
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading