Shibex
Shibex

Reputation: 61

Getting undefined when trying to fetch data from an api - React

So im trying to set a variable with the data im getting from the API.

when im console logging it into my browser everything works fine but when im trying to set my variable on React the variable ending up undifeind. can someone tell me what am i missing here?

this is my code :

import React from 'react'

let news
function getNews () {
  fetch(
    'https://newsapi.org/v2/top-headlines?country=us&apiKey=6f9cf5e6b9684bd3a6a8117e35feb1c9'
  )
    .then(res => res.json())
    .then(data => {
      news = data
      return news
    })
}

getNews()
class NewsApi extends React.Component {
  render () {
    return <div />
  }
}

export default NewsApi

Upvotes: 2

Views: 7687

Answers (3)

Laurens Deprost
Laurens Deprost

Reputation: 1691

Please look at the snippet below for an example implementation.

Some key points:

  • Try to do your data fetching in componentDidMount()
  • Use state and this.setState()
    This will cause an automatic rerender after the data is fetched.
    Handy for working with asynchronous function calls: these tools make it easy to use data in components without knowing when it will become available and help eliminate the undefined issue you were having.

class NewsApi extends React.Component {
  state = {
    articles: []
  };

  componentDidMount() {
    fetch(
      "https://newsapi.org/v2/top-headlines?country=us&apiKey=6f9cf5e6b9684bd3a6a8117e35feb1c9"
    )
      .then(res => res.json())
      .then(data => data.articles)
      .then(articles => {
        this.setState({ articles });
      });
  }

  render() {
    return (
      <div>
        <h1>Articles</h1>
        <ArticleList articles={this.state.articles} />
      </div>
    );
  }
}

const ArticleList = props => (
  <div>
    <ol>
      {props.articles.map((article, index) => (
        <div key={index}>
          <li>{article.title}</li>
          <br />
        </div>
      ))}
    </ol>
  </div>
);

function App() {
  const appStyle = {
    fontFamily: "sans-serif",
    textAlign: "center"
  };

  return (
    <div className="App" style={appStyle}>
      <NewsApi />
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Upvotes: 0

Tarreq
Tarreq

Reputation: 1365

try this : It outputs what you want. ** Notes: Fetch is Async functions, means, it has to be called inside (for example) life cycle method like componentDidMount.

import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      news: []
    };
  }

  componentDidMount() {
    fetch(
      "https://newsapi.org/v2/top-headlines?country=us&apiKey=6f9cf5e6b9684bd3a6a8117e35feb1c9"
    )
      .then(response => response.json())
      .then(data => this.setState({ news: data.articles }));
  }

  render() {
    console.log(this.state.news);
    return <div />;
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Here is a live example (You can see console output also)\

Edit 487m15996x

Upvotes: 1

sdkcy
sdkcy

Reputation: 3548

Your getNews function is async. You should use state to save your data. So, as soon as the data fetched, you can use the data in your component.

import React from 'react';

class NewsApi extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            news: []
        };
        this.getNews = this.getNews.bind(this);
    }

    componentDidMount() {
        this.getNews()
    }

    getNews() {
        fetch('https://newsapi.org/v2/top-headlines?country=us&apiKey=6f9cf5e6b9684bd3a6a8117e35feb1c9')
            .then(res => res.json())
            .then((data) => {
                this.setState({news:data.articles});
            });
    }

    render() {
        console.log(this.state.news)
        return (
            <div></div>
        );
    }
}

export default NewsApi;

Upvotes: 2

Related Questions