Search code examples
javascriptreactjsfoursquare

React component lifecycle API request


I am trying to make a request to the FourSquare API which desires a time object being sent in the format of YYYYMMDD. I have written a function that produces the time object however I am having issues using it within my React app.

I make a call within my Profile component:

'use strict'

import React, { Component } from 'react'
import request from 'superagent'

import TimeService from './services/time'
import config from './config'

class Profile extends Component {

componentDidMount() {
  TimeService.getCurrentTime((err, currentDate) => {
    this.setState({
      time: currentDate
    })
  })
}

componentWillMount() {

  let currentTime = this.state.time
  let venue = '4dd64e9de4cd37c8938e7b83'
  //let venue = this.props.venueId
  let clientId = config.CLIENT_ID
  let clientSecret = config.CLIENT_SECRET

  request.get(`https://api.foursquare.com/v2/venues/${venue}/hours/?\&client_id=${clientId}&client_secret=${clientSecret}&v=${currentTime}`)
    .accept('json')
    .end((err, res) => {
      if(err) return
        let result = res.body
        console.log(res.body)
        console.log(result.response.hours.timeframes)
  })
}

When I load app in Chrome I have the error message of: bundle.js:44492 Uncaught TypeError: Cannot read property 'time' of null

My guess is that I need to re-order the functions within the component mounting methods, however I am unsure how to.


Solution

  • Various methods are executed at specific points in a component's lifecycle.

    • componentWillMount is executed once before the initial rendering occurs.

    • componentDidMount is executed once after the initial rendering.

    You are setting your state when the component is mounted in componentDidMount but using it before in componentWillMount.

    So when you're using:

    let currentTime = this.state.time
    

    It's not defined yet so you're getting an Cannot read property 'time' of null.

    You should set your state in componentWillMount, the render() will see the updated state and will be executed only once despite the state change.

    After that, once the component is mounted, you can execute your call to the Foursquare API, your time property in the state will be defined so it'll no longer trigger an error.

    You can get more informations regarding components lifecycle in the documentation.

    This documentation also states that the preferred method to send AJAX requests is componentDidMount.

    If you want to integrate with other JavaScript frameworks, set timers using setTimeout or setInterval, or send AJAX requests, perform those operations in this method.