Jonathan Small
Jonathan Small

Reputation: 1079

reactJS map function not working as expected

I have a reactJS application where I am trying to dynamically render some data that I read in with a fetch() promise. This is the code of my application:

    import React from 'react'; 
import '../styles/app.css'; 

//think of react components as functions 
class Testpage2 extends React.Component { 

constructor(props) { 
    super(props); 
    this.state = { 
        numberOfRecords: 0,
        productArray: [{
            barcode: '',
            name: ''
        }]
    }; 

}  

componentDidMount() { 

    let currentComponent = this; 
    var recordCount = 0;
    var tempData = [];

    //Make use of the API not the web service. 
    let url = "http://wmjwwebapi-dev.us-west-2.elasticbeanstalk.com/api/getdata"; 
    const options = { method: 'GET' }; 

    fetch(url, options) 
    .then(function(response) { 
        return response.json(); 
    }) 
    .then(function(myJson) { 
        if (myJson == undefined) 
        { 
        console.log("fetch failed"); 
        } 
    else 
    { 
        //inspect the data that the WebAPI returned 
        var return_code = myJson[0].return_code; 
        if (return_code == "Default Return code"){ 
            recordCount = -2; 
        } else { 
            tempData = JSON.parse(myJson[0].return_string);
            recordCount = tempData.barcode.length; 
        }
        currentComponent.setState(
        {
            numberOfRecords: recordCount,
            productArray: currentComponent.state.productArray.push(
            { 
                name: tempData.name, 
                barcode: tempData.barcode 
            })
        }
    );
    } 
    }); 
} 

render() { 
    console.log(this.state.productArray);
    return ( 
        <div> 
            { this.state.productArray.map((prod, index) => <li key={index}>{prod.barcode}</li>)}
        </div> 
    ) 
} 
} 

export default Testpage2

and this is the error message that I am getting:

Uncaught (in promise) TypeError: this.state.productArray.map is not a function
at Testpage2.render (testpage2.js:67)

This is the result of the console.log() that I added in the render() function:

enter image description here

I'm not really sure what this error is telling me or how to go about debugging the issue.

Any help is greatly appreciated. Thank you.

Upvotes: 0

Views: 1110

Answers (4)

Patrick Hollweck
Patrick Hollweck

Reputation: 6665

The return type of array.push is the new length of the array aka a number

So you set the state property productArray to a number and then try to call number.map which is not defined

How to fix?

push first and then use that array to set the state

const updatedArray = [...currentComponent.state.productArray] 
updatedArray.push({ name: tempData.name, barcode: tempData.barcode })

currentComponent.setState({
   numberOfRecords: recordCount,
   productArray: updatedArray
}

Resources: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push

Upvotes: 1

inostia
inostia

Reputation: 8023

The JavaScript Array.push method does not return the modified array, it returns the new length of the array, which is a number. Numbers in JavaScript do not have the map method.

You need to do first create a clone of the productArray, then push the new data, and finally set state:

const newProductArray = [...currentComponent.state.productArray]
newProductArray.push({ 
    name: tempData.name, 
    barcode: tempData.barcode 
})
currentComponent.setState(
    {
        numberOfRecords: recordCount,
        productArray: newProductArray
    }
)

See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push

Upvotes: 0

Andriy
Andriy

Reputation: 15442

Array's push() function returns integer, so you cannot call map() function on it. Try to change your function to:

currentComponent.setState({
  numberOfRecords: recordCount,
  productArray: [...currentComponent.state.productArray, { 
    name: tempData.name, 
    barcode: tempData.barcode 
  }]
})

Upvotes: 0

kristaps
kristaps

Reputation: 1723

According to MDN:

The push() method adds one or more elements to the end of an array and returns the new length of the array.

It appears that your code expects that Array.push() will return the modified array itself:

productArray: currentComponent.state.productArray.push(...

To prevent the state corruption you should do construct the new array separately, before invoking setState().

Upvotes: 0

Related Questions