Home > Enterprise >  Got this error: [ TypeError: Cannot read properties of undefined (reading 'map') ], Please
Got this error: [ TypeError: Cannot read properties of undefined (reading 'map') ], Please

Time:12-12

I'm building a react project using redux. I'm getting this weird error, i'm not able to resolve: The error I see in my browser window:

Contacts.render C:/Users/lenovo/Desktop/contactmanager_redux/src/components/contacts/Contacts.js:18

 15 | const { contacts } = this.props;
  16 | return (
  17 |   <React.Fragment>
> 18 |     <h1 className="display-4 mb-2">
     | ^  19 |       <span className="text-success">Contact</span> List
  20 |     </h1>
  21 |     {contacts.map(contact => (

View compiled

▶ 22 stack frames were collapsed.

Function.mapToProps C:/Users/lenovo/Desktop/contactmanager_redux/src/actions/contactActions.js:7

4 | 
   5 | export const getContacts = () => async dispatch => {
   6 |   const res = await axios.get("https://jsonplaceholder.typicode.com/users");
>  7 |   dispatch({
   8 |     type: GET_CONTACTS,
   9 |     paylaod: res.data
  10 |   });

View compiled

this error came out when I tried to fetch the data using axios and tried to add the payload in the reducer file. I created separate action file and then brought the code to reducer using dispatch function.

Here is my Contacts.js file:

import React, { Component } from 'react';
import Contact from './Contact';
import {connect} from 'react-redux';
import PropTypes from 'prop-types';
// import {GET_CONTACTS} from '../../actions/types';
import {getContacts} from '../../actions/contactActions';

class Contacts extends Component {

  componentDidMount(){
    this.props.getContacts;
  }
  
  render() {
    const { contacts } = this.props;
    return (
      <React.Fragment>
        <h1 className="display-4 mb-2">
          <span className="text-success">Contact</span> List
        </h1>
        {contacts.map(contact => (
          <Contact key={contact.id} contact={contact} />
        ))}
      </React.Fragment>
    );
  }
}

Contacts.propTypes = {
  contacts: PropTypes.array.isRequired,
  getContacts: PropTypes.func.isRequired
}

const mapStateToProps = (state) => ({
  contacts: state.contact.contacts
});

/*const mapDispatchToProps = (dispatch) => (
  {
    getContacts: () => (dispatch({type: GET_CONTACTS}))
  }
)*/

export default connect(mapStateToProps, getContacts)(Contacts);

my ContactActions.js code:

import {GET_CONTACTS, DELETE_CONTACT, ADD_CONTACT} from './types';
import axios from 'axios';


export const getContacts = () => async dispatch => {
  const res = await axios.get("https://jsonplaceholder.typicode.com/users");
  dispatch({
    type: GET_CONTACTS,
    paylaod: res.data
  });
}

export const deleteContact = (id) => {
  return {
    type: DELETE_CONTACT,
    payload: id
  }
}

export const addContact = (contact) => {
  return {
    type: ADD_CONTACT,
    payload: contact
  }
}

ContactReducer.js code:

    import {GET_CONTACTS, DELETE_CONTACT, ADD_CONTACT} from '../actions/types';

const initialState = {
  contacts: []
};

export default function(state = initialState, action){
  switch(action.type){
    case GET_CONTACTS:
      return {
        ...state,
        contacts: action.payload
      };

    case DELETE_CONTACT:
      return {
        ...state,
        contacts: state.contacts.filter(contact => contact.id !== action.payload)
      }

    case ADD_CONTACT:
      return {
        ...state,
        contacts: [action.payload, ...state.contacts]
      }

    default:
      return state;
  }
}

CodePudding user response:

Initally Contacts will not have data .Do conditional render like this so only the render will happen when data is available in contacts .

{contacts && contacts.map(contact => (
          <Contact key={contact.id} contact={contact} />
        ))}

CodePudding user response:

There are couple of problems in your Contacts component:

1- Since you have commented mapDispatchToProps, actually you haven't send getContacts function to your Contacts component as a prop.

2- You haven't call getContacts in the componentDidMount. you just has wirtten this.props.getContacts; while getContacts must be an function and you have to call it, in order to fetch data.

I edited your MyContact.js file a bit, please try on this:

MyContact.js

import React, { Component } from 'react';
import Contact from './Contact';
import {connect} from 'react-redux';
import PropTypes from 'prop-types';
// import {GET_CONTACTS} from '../../actions/types';
import {getContacts as fetchContacts} from '../../actions/contactActions';

class Contacts extends Component {

  componentDidMount(){
    this.props.getContacts();
  }

  render() {
    const { contacts = [] } = this.props;
    return (
      <React.Fragment>
        <h1 className="display-4 mb-2">
          <span className="text-success">Contact</span> List
        </h1>
        {contacts.map(contact => (
          <Contact key={contact.id} contact={contact} />
        ))}
      </React.Fragment>
    );
  }
}

Contacts.propTypes = {
  contacts: PropTypes.array.isRequired,
  getContacts: PropTypes.func.isRequired
}

const mapStateToProps = (state) => ({
  contacts: state.contact.contacts
});

const mapDispatchToProps = (dispatch) => (
  {
    getContacts: () => (dispatch(fetchContacts())
  }
)

export default connect(mapStateToProps, mapDispatchToProps)(Contacts);
  • Related