0

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.

11
  • Can you tell me what the result is when you console.log "this.state.productArray" in the render function? Commented Aug 26, 2018 at 22:37
  • I edited the post to include an image from the console.log() Commented Aug 26, 2018 at 22:48
  • Thanks but I already answered your question... Can you confirm that it works then? Commented Aug 26, 2018 at 22:50
  • Works perfectly! Thank you so much. Commented Aug 26, 2018 at 22:54
  • Can you check that Array.isArray(this.state.productArray) is true? Commented Aug 26, 2018 at 22:57

4 Answers 4

1

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

Sign up to request clarification or add additional context in comments.

3 Comments

It's not a good idea to modify the state manually. The recommended way is always to use setState method.
Nice one buddy.
Still better way of push elements to an array in React is currentComponent.setState(prevState =>({productArray: [...prevState.productArray, { name: tempData.name, barcode: tempData.barcode }]}));
0

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().

Comments

0

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 
  }]
})

Comments

0

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

3 Comments

Still better way of push elements to an array in React is currentComponent.setState(prevState =>({productArray: [...prevState.productArray: { name: tempData.name, barcode: tempData.barcode }]}));
Do you have a source for that syntax @Think-Twice? I've never seen : used in an array, as far as I know it's reserved for objects.
Sorry it’s typo mistake it should be comma not colon

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.