user9013856
user9013856

Reputation: 328

react map is not a function

Yo guys, getting error 'contacts.map is not a function' not sure why is that ? just starting in react maybe missing something obvious. I'm getting the data when I console log all good. code below:

import React, { Component } from 'react'
import axios from 'axios';


class Contacts extends Component {
 constructor(){
 super();

 this.state = {
    contacts: [],
 }

}


componentDidMount(){
    axios.get('url')
    .then(response => {
    this.setState({ contacts: response.data });
    })
    .catch(function (error) {
    console.log(error);
    })
}


render() {
    const { contacts } = this.state 
    return(
    <div>
        {contacts.map(contact => (
            <h1>contact.hello</h1>
        ))}

    </div>
    )
}
}

export default Contacts;

Apparently its an object not an array...

How can i render this object then?

It has one property for now but will have more later on: tried JSON.stringify(obj)

{hello: "test"}

Upvotes: 2

Views: 149

Answers (4)

Asaf Aviv
Asaf Aviv

Reputation: 11800

From react docs:

Note:

These methods are considered legacy and you should avoid them in new code:

  • UNSAFE_componentWillMount()

When you want to wrap an object you can simply wrap it in brackets

class Contacts extends Component {
  constructor() {
    super();

    this.state = {
      contacts: [],
    }
  }

  componentDidMount() {
    axios.get('url')
      .then(({ data }) => {
        this.setState({ contacts: [data] });
      })
      .catch((error) => {
        console.log(error);
      });
  }

  render() {
    const { contacts } = this.state;
    return (
      <div>
        {contacts.map(contact => (
          <h1 key={/* unique key */}>contact.hello</h1>
        ))}
      </div>
    );
  }
}

Upvotes: 2

Hemadri Dasari
Hemadri Dasari

Reputation: 34014

Since the contacts is an object I would recommend you to do Object.keys and then .map on it so that you can get object keys and it’s values.

One more thing never forget to add unique key to the parent jsx element when you iterate array of data or an object like below.

 <div>
    {Object.keys(contacts).map((name, index) => (
        <h1 key={'Key'+index}>{contacts[name]}</h1>
    ))}

</div>

Upvotes: 3

davidev
davidev

Reputation: 314

Use async await to get the response before the component is mounted

import React, { Component } from 'react'
import axios from 'axios';


class Contacts extends Component {
  constructor(){
   super();

   this.state = {
      contacts: [],
   }
  }

  async componentWillMount(){
    const response = await axios.get('url')
    this.setState({ contacts: response.data })
  }

  render() {
      const { contacts } = this.state
      return(
      <div>
          {contacts.map(contact => (
              <h1>contact.hello</h1>
          ))}

      </div>
      )
   }
}

export default Contacts;

Upvotes: 0

Nicola Peluchetti
Nicola Peluchetti

Reputation: 76910

The problem is that you set contacts to response.data, which evidently it's not an array.

componentDidMount fires after the component is mounted and tries to get the string 'url'. When state is updated, the component is redrawn and it gives the error.

Upvotes: 5

Related Questions