Search code examples
reactjsstatereact-lifecycle

Using state with componentDidMount


I want to fetch data that returns successfully after componentDidMount, but before there is an error that singer.data is undefined:

// imports
export default class LookSinger extends Component {
    state = {
        singer: {}
    }
    componentDidMount () {
        let { singer } = this.props.location.state;
        singer = singer.replace(/ /g,"+");
        const fetchData = async () => {
        try {
            const response = await fetch(
                `http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&artist=${singer}&api_key=a3c9fd095f275f4139c33345e78741ed&format=json`
            );
            const data = await response.json();
            this.setState({
                singer: data
            })
          } catch (error) {
            console.log(error.message);
          }
        }
        fetchData();
    }
      render() {
          let singer = this.state.singer
        return(
            <div>
                {console.log(singer.artist.name)} // gives undefined but after fetching artist.name absolutely exists
            </div>
        )
      }
}

Url is:http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&artist=Ariana+Grande&api_key=a3c9fd095f275f4139c33345e78741ed&format=json


Solution

  • The problem is here:

    {console.log(singer.artist.name)}

    In the initial render, singer.artist is undefined and if you call singer.artist.name it will throw error. name of undefined.... You just need to wait for data to fetch and update the state.

    Try like this

    export default class LookSinger extends Component {
      state = {
        singer: {}
      }
      componentDidMount () {
        let { singer } = this.props.location.state;
        singer = singer.replace(/ /g,"+");
        const fetchData = async () => {
        try {
            const response = await fetch(`http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&artist=${singer}&api_key=a3c9fd095f275f4139c33345e78741ed&format=json`);
            const data = await response.json();
            this.setState({ singer: data })
          } catch (error) {
            console.log(error.message);
          }
        }
        fetchData();
      }
      render() {
        const { singer } = this.state
        if (!singer.artist) { // <-- Check if the data is present or not.
          return <div>Loding singer info...</div>
        }
        return(
          <div>
            <h1>{singer.artist.name}</h1>
          </div>
        )
      }
    }