Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly render Component after this.setState in React

I have this React component

import React, { Component } from "react";

export default class ResourceForField extends Component {
    constructor() {
        super();
        this.state = {
            resources: [],
        };
    }
    componentDidMount() {
        // get the resources from the Link props and save it into the state
        this.setState({
            resources: this.props.location.resources,
        });
    }

    // This component gets the id of current learningField from the url
    // and the rest(like the resources) from the Link component
    render() {
        return (
            <div>
                {this.state.resources.map(res => (
                    <div>test</div>
                ))}
            </div>
        );
    }
}

It gets the resources from the Link component, and that works fine. If I check out the state of the Component from the dev tools, the state looks right. And I thought with my logic this should work. So firstly, the state is empty, the component gets rendered, since the state is empty it doesn't render any components. Then, setState gets called, it gets all the resources and saves them into the state, and then the component would re-render, and it should work, but it doesn't. I'm getting a TypeError: Cannot read property 'map' of undefined error. What is the correct way to do this and how do I fix this?

like image 504
randomboiguyhere Avatar asked Oct 28 '25 05:10

randomboiguyhere


1 Answers

Try this code:

import React, { Component } from "react";

export default class ResourceForField extends Component {
    constructor() {
        super();
        this.state = {
            resources: this.props && this.props.location && this.props.location.resources?this.props.location.resources:[],
        };
    }
    componentDidMount() {

    }

    // This component gets the id of current learningField from the url
    // and the rest(like the resources) from the Link component
    render() {
        return (
            <div>
                {this.state.resources.map(res => (
                    <div>test</div>
                ))}
            </div>
        );
    }
}

Or use directly props

import React, { Component } from "react";

export default class ResourceForField extends Component {
    constructor() {
        super();

    }

    // This component gets the id of current learningField from the url
    // and the rest(like the resources) from the Link component
    render() {
        return (
            <div>
                { 
                  this.props && this.props.location && 
                  this.props.location.resources
                    ?this.props.location.resources.map(res => (
                    <div>test</div>
               ))
             :null
              }
            </div>
        );
    }
}

Or use componentWillReceiveProps or getDerivedStateFromProps life cycle methods. Check this.props.location.resources is array. See more: https://hackernoon.com/replacing-componentwillreceiveprops-with-getderivedstatefromprops-c3956f7ce607

like image 185
Ramil Aliyev Avatar answered Oct 29 '25 21:10

Ramil Aliyev



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!