Author avatar

Kimaru Thagana

TypeError Handling in React.js for Map Function

Kimaru Thagana

  • Oct 8, 2020
  • 7 Min read
  • 62 Views
  • Oct 8, 2020
  • 7 Min read
  • 62 Views
Web Development
Front End Web Development
Client-side Frameworks
React

Introduction

During design and development of frontend interfaces in React.js, working with data from different sources is quite normal and frequent. This data needs to be parsed accurately within your React app. If the data isn't parsed correctly, you will run into errors, one of these being Uncaught TypeError: this.props.data.map is not a function.

In this tutorial, you will learn why this error occurs and how to fix it. This guide assumes that you have basic knowledge of React.js.

Why This Error Occurs

So you have just fetched data from an API in your parent component, and you have passed the data to your child component via props, but trying to parse this data in your child component with the .map() function gives this error: Uncaught TypeError: this.props.data.map is not a function. You have verified that data is being fetched and passed into your child component correctly.

What's going on?

This error occurs because your data is not an array. The .map() function only works with arrays. First, you'll need to confirm your data type. Second, you'll need to transform your data into an array.

Example Scenario

Assuming you already have a React app set up, the code below simulates a data object fetched from an API. This data will be passed down to your child component. For a refresher on this topic, read this guide.

You will be using The Movie Database API. For a detailed guide to parsing JSON data, refer to this tutorial.

Here is sample data from the API.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
{
	"page": 1,
	"results": [{
			"poster_path": "/e1mjopzAS2KNsvpbpahQ1a6SkSn.jpg",
			"adult": false,
			"overview": "From DC Comics comes the Suicide Squad, an antihero team of incarcerated supervillains who act as deniable assets for the United States government, undertaking high-risk black ops missions in exchange for commuted prison sentences.",
			"release_date": "2016-08-03",
			"genre_ids": [
				14,
				28,
				80
			],
			"id": 297761,
			"original_title": "Suicide Squad",
			"original_language": "en",
			"title": "Suicide Squad",
			"backdrop_path": "/ndlQ2Cuc3cjTL7lTynw6I4boP4S.jpg",
			"popularity": 48.261451,
			"vote_count": 1466,
			"video": false,
			"vote_average": 5.91
		},
		{
			"poster_path": "/lFSSLTlFozwpaGlO31OoUeirBgQ.jpg",
			"adult": false,
			"overview": "The most dangerous former operative of the CIA is drawn out of hiding to uncover hidden truths about his past.",
			"release_date": "2016-07-27",
			"genre_ids": [
				28,
				53
			],
			"id": 324668,
			"original_title": "Jason Bourne",
			"original_language": "en",
			"title": "Jason Bourne",
			"backdrop_path": "/AoT2YrJUJlg5vKE3iMOLvHlTd3m.jpg",
			"popularity": 30.690177,
			"vote_count": 649,
			"video": false,
			"vote_average": 5.25
		},
		{
			"poster_path": "/hU0E130tsGdsYa4K9lc3Xrn5Wyt.jpg",
			"adult": false,
			"overview": "One year after outwitting the FBI and winning the public’s adulation with their mind-bending spectacles, the Four Horsemen resurface only to find themselves face to face with a new enemy who enlists them to pull off their most dangerous heist yet.",
			"release_date": "2016-06-02",
			"genre_ids": [
				28,
				12,
				35,
				80,
				9648,
				53
			],
			"id": 291805,
			"original_title": "Now You See Me 2",
			"original_language": "en",
			"title": "Now You See Me 2",
			"backdrop_path": "/zrAO2OOa6s6dQMQ7zsUbDyIBrAP.jpg",
			"popularity": 29.737342,
			"vote_count": 684,
			"video": false,
			"vote_average": 6.64
		}
	]

}
json

Here is a simple React app to simulate fetching data from your API and setting state.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import React, {Component} from 'react';
import axios from 'axios'
import 'bootstrap/dist/css/bootstrap.min.css';
import {Button, Card, Col, Row} from "react-bootstrap";


class App extends Component{
  constructor(props) {
    super(props);
    this.state =({
      movies: ""
    })
  }
  componentDidMount() {
    let url = "https://api.themoviedb.org/3/discover/movie?api_key=abc12345";
    axios.get(url+"&sort_by=popularity.desc&page=1")
        .then(response => {
          console.log(response.data.results)
            this.setState({
                movies: response.data.results
            })
        })
        .catch(error => {
          console.log(error)
        })
  }
}
js

In the sample code above, you have fetched your data from an API and set the movie state to use this data. Notice how you have set the movie state as you will come back to this later.

Finish up by creating a child component and passing your data from App.js, which is the parent component to your child component.

Add this code to your parent component.

1
2
3
4
5
6
render()
 {
       return(
           <ChildComponent data={this.state.movies}/>
       )
    }
js

Here's how your child component should look.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import React, {Component} from "react";
import {Row,Col, Card} from "react-bootstrap";

class ChildComponent extends Component{
    constructor(props) {
        super(props);
        
    }

    render() {
      
        return (
            <Row>
                {this.props.data.map((movie, index) => (
                        <Col key={index} sm={4} md={4} lg={3}>
                            <Card style={{ width: '18rem' }}>
                                <Card.Img variant="top" src={"http://image.tmdb.org/t/p/w300//"+movie.poster_path} />
                                <Card.Body>
                                    <Card.Title>{movie.title}</Card.Title>
                                    <Card.Text>
                                        {movie.overview}
                                    </Card.Text>
                                </Card.Body>
                            </Card>
                        </Col>
                    )
                )}
            </Row>
        )
    }
}
export default ChildComponent
js

A quick recap: You have simulated a simple app to fetch data from TMDB API and set your state. You have also passed your fetched data to your child component. To parse the data, you have used a React bootstrap card component. If you try running your app, you should receive the error TypeError: this.props.data.map is not a function.

Refer back to where you set your state and the sample API response. You'll notice that if you set the state as it is with your JSON object, this error occurs. Your .map() function will not work with objects. You will need to enclose your object in an array.

Make a simple change to your state within the parent component: Change movies: "" to movies: [].

Now run your app again. The error disappears, and your data is parsed through correctly.

Conclusion

Being able to understand and debug errors in React is a skill that can be developed by constant practice. React and frontend developer jobs heavily require this skill. To further build on this guide, you can learn more about React contexts on the official React.js site

0