Vignesh Veeran
Vignesh Veeran

Reputation: 95

React app: Undefined value after fetch

I have the following code where i fetch data from twitter API feed. I use a call back function and setState the values to my state properties. When I use it in render to just console and see the value then it shows

"Cannot read property 'created_at' of undefined".

I think it is trying to fetch before it is even available. I don't know what to do here. Can someone please help. When i use console.log(this.state.twitterfeed.techcrunch[0]) I do not get any error.

I got the object

But when I use console.log(this.state.twitterfeed.techcrunch[0].created_at) then I got error

    class Columns extends Component {
      constructor() {
        super();
        this.state = {
          twitterfeed: {
            techcrunch: [],
            laughingsquid: [],
            appdirect: []
          }
        };
      }
      updateTwitterFeed = (data, user) => {
        var twitterfeed = { ...this.state.twitterfeed };
        if (user === "appdirect") {
          twitterfeed.appdirect = data;
        } else if (user === "laughingsquid") {
          twitterfeed.laughingsquid = data;
        } else {
          twitterfeed.techcrunch = data;
        }
        this.setState({ twitterfeed });
      };

      componentDidMount() {
        fetch(
          "http://localhost:7890/1.1/statuses/user_timeline.json?count=30&screen_name=techcrunch"
        )
          .then(response => response.json())
          .then(data => this.updateTwitterFeed(data, "techcrunch"));
        fetch(
          "http://localhost:7890/1.1/statuses/user_timeline.json?count=30&screen_name=laughingsquid"
        )
          .then(response => response.json())
          .then(data => this.updateTwitterFeed(data, "laughingsquid"));
        fetch(
          "http://localhost:7890/1.1/statuses/user_timeline.json?count=30&screen_name=appdirect"
        )
          .then(response => response.json())
          .then(data => this.updateTwitterFeed(data, "appdirect"));
      }

      render() {
        return (
          <div className="container mx-0">
            <div className="row">
              <div className="col-4 col-md-4">
                {console.log(this.state.twitterfeed.techcrunch[0].created_at)}
                <Column tweet={this.state.twitterfeed.techcrunch} />
              </div>
            </div>
          </div>
        );
      }
    }

Upvotes: 2

Views: 2133

Answers (2)

Diego Gallegos
Diego Gallegos

Reputation: 1752

I have a couple of recommendations here.

First of all, try to consolidate your fetch logic using Promise.all.

Take a look at the documentation here. This will make

fetch(..).then(..)
fetch(..).then(..)
fetch(..).then(..)

into

Promise
    .all([fetch(..), fetch(..), fetch(..)])
    .then(...) // all 3 responses here

Also when rendering a React component componentDidMount() runs after render(). Take a look at react lifecycle here.

So the solution to be sure that the data you want to render is available is to have a flag on state such as:

this.state = { loading: True, ... } // constructor

Promise
    .all([...])
    .then(...)
    .then(args => 
        this.setState({loading: False});
     ...) // componentDidMount()

render() { 
    if(this.state.loading)
        return  <div>Loading...</div>

    return (
       // your component with data already set into the state :)
    )
}

Upvotes: 0

Tholle
Tholle

Reputation: 112807

this.state.twitterfeed.techcrunch[0] will be undefined before your fetch is complete, so trying to access created_at on that will give rise to your error.

You could e.g. render null until the techcrunch array has been filled after the request.

class Columns extends Component {
  // ...

  render() {
    const { techcrunch } = this.state.twitterfeed;

    if (techcrunch.length === 0) {
      return null;
    }

    return (
      <div className="container mx-0">
        <div className="row">
          <div className="col-4 col-md-4">
            <Column tweet={techcrunch} />
          </div>
        </div>
      </div>
    );
  }
}

Upvotes: 6

Related Questions