简体   繁体   中英

TypeError: Cannot read property 'map' of undefined when parsing JSON

I got the error: TypeError: Cannot read property 'map' of undefined when I am trying to build a const value to inject inside a Gallery. The const is build using a JSON

Here is the class where the issue happened:


class ClassDetails extends React.Component {
    
    constructor(props, context) {
        super(props);
        this.state = {anchorEl: null, 
            showJoin: false,
            classDetailsInfo: ''};
    }


    componentDidMount = () => {
        this.setState({classDetailsInfo: ClassDataUseCase.getClassDetails()})
    }

      render() {

        const CLASS_PIC_LIST = this.state.classDetailsInfo.classpic
        const GALLERY = CLASS_PIC_LIST.map((pic) => ({
            src: pic,
            thumbnail: pic, //.replace("1280","_480"), // for example
            thumbnailWidth: 156,
            thumbnailHeight: 156
            }));
       ...
    }
}

export default ClassDetails;

The exact error is TypeError: Cannot read property 'map' of undefined and happened when doing const GALLERY = CLASS_PIC_LIST.map((pic) => ({

The classDetailsInfo is set using ClassDataUseCase.getClassDetails() defined as below:

class ClassDataUseCase {

    static getAllClasses() {
        return JSON.parse(ClassDetailsData.Classes)
    }
    static getClassDetails(id) {
        var jsonClasses = JSON.parse(ClassDetailsData.Classes);
        for(let k=0;k< jsonClasses.length;k++){
            if(jsonClasses[k].id===id){
              return jsonClasses[k];
            }
        }
    }
}

and the data are coming from the ClassDetailsData which is a JSON as defined below:

class ClassDetailsData {
    static Classes = [{
            "id": "c000001",
            "title": "Cook like a chef",
            "price": "5",
            "teacher": "Arthur Patrick",
            "teacherpic": "https://cdn.pixabay.com/photo/2015/03/03/08/55/portrait-657116_1280.jpg",
            "teacherid": "u0000000001",
            "desc": "Always want to learn to cook, that's the place you need to be",
            "bring": "Your fun , your motivation and you",
            "tags": [],
            "address": {
                "id":"",
                "Name": "Joel Robuchon",
                "address1": "3799 S Las vegas boulevard",
                "address2": "",
                "city": "las vegas",
                "county": "Clark",
                "zip": "89109",
                "state": "Nevada",
                "country": "United States"
            },
            "date": "2021/09/01",
            "time": "1:00PM",
            "duration": "2",
            "classpic": ["https://cdn.pixabay.com/photo/2014/06/16/23/10/spice-370114_1280.jpg",
            "https://cdn.pixabay.com/photo/2015/08/13/18/47/spices-887348_1280.jpg", 
            "https://cdn.pixabay.com/photo/2015/04/20/13/30/kitchen-731351_1280.jpg",
            "https://cdn.pixabay.com/photo/2015/07/02/10/40/writing-828911_1280.jpg"],
            "reviews": [{
                "name": "Gabby Caldwell",
                "profilePic":"https://cdn.pixabay.com/photo/2015/03/03/08/55/portrait-657116_960_720.jpg",
                "rate": "5",
                "total_review": "13",
                "text": "Rachel was such a kind and knowledgeable guide. She took us to see some hidden coves that a lot of tourists probabaly miss. I’m keeping the map I made FOREVER!!!"
            }],
        }, 
        {........}
        ];
}

export default ClassDetailsData;

I do not understand why it's complaining. any idea? thanks

In the constructor you are declaring your state with classDetailsInfo as a empty string, and a string doesn't have a .map method on it.

this.state = {anchorEl: null, 
            showJoin: false,
            classDetailsInfo: ''};

You need to declare the classDetailsInfo as an appropriate type for it not to break on the initial render.

this.state = {anchorEl: null, 
            showJoin: false,
            classDetailsInfo: {
              classpic: []
            }
};

In your state you define classDetailsInfo as a string, that's the reason why you are getting that error

You should set initially it equal to an empty array [] to avoid unexpected behavior

 class App extends React.Component { constructor(props) { super(props); this.state = { classList: '' } } componentDidMount() { this.setState({classList: ["name", "data", "test"]}); } render() { return <div> {this.state.classList.map(cl => <span>{cl}</span>)} </div> } } ReactDOM.render(<App/>, document.getElementById('root'));
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.1.1/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.1.1/umd/react-dom.production.min.js"></script> <div id="root"></div>

You can look this simple example, If I change the value of state key classList to an [] every thing work as expected. But now It reproduces the same error you get

 class App extends React.Component { constructor(props) { super(props); this.state = { classList: [] } } componentDidMount() { this.setState({classList: ["name", "data", "test"]}); } render() { return <div> {this.state.classList.map(cl => <span>{cl}</span>)} </div> } } ReactDOM.render(<App/>, document.getElementById('root'));
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> <div id="root"></div>

In the second example after I initialize classList to an array it work.

There might be case when this.state.classDetailsInfo.classpic don't have the value. So initialize it with a default [] if it does not have any value.

You can do it like this:

const CLASS_PIC_LIST = this.state.classDetailsInfo.classpic || [];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM