0

Im trying to get json data from an api using react and insert it into an html page. Here's the function:

function GetApiContent() {
  let value = fetch(api2)
    .then(response => response.json())
    .then(results => {
      console.log(results.title)

      return {
        title: results.title,
        date: results.date,
        hdurl: results.hdurl,
        explanation: results.explanation,
      }
    })
    .catch(err => {
      console.log(err)
    })

  return (
    <div>
      <h3>{value.title}</h3>
    </div>
  )
}

class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h1 className="App-title">Api test</h1>
          <Hola message="hello" />
        </header>

        <GetApiContent />
        <p className="App-intro">
          To get started, edit <code>src/App.js</code> and save to reload.
        </p>
      </div>
    )
  }
}

Console log works and returns title but when i return it in the function it shows the h3 tag empty in the web page.

3
  • That's because when you return your h3 block, the fetch call (which is asynchronous) has likely not completed yet, so value.title is not set. Try putting it all within the then handler. Commented Nov 9, 2017 at 10:28
  • Actually the implementation seems correct. Can you put console before the return of 'GetApiContent' method and check whether the variable value is formed correctly Commented Nov 9, 2017 at 10:29
  • It seems value is not formed so i think Jaxx is correct. I don't understand what you mean by putting it all in the .then, l tried to return the html code inside the .then but i get the error: Objects are not valid as a React child. Commented Nov 9, 2017 at 10:38

2 Answers 2

4

fetch is an asynchronous, Promise-based operation and it doesn't return value right away. It returns Promise. This is why your code is not working. You're basically trying to display Promise's value property which is not what you want. You want to wait for the Promise to resolve (in other words: for fetch to finish request and resolve to the response). You can do it that way to display value from your api:

const getApiContent = () => fetch(api2).then(response => response.json())

class App extends Component {
  state = {
    title: ''
  }

  componentDidMount() {
    getApiContent()
      .then(result => this.setState({ title: result.title }))
      .catch(err => console.log(err))
  }

  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h1 className="App-title">Api test</h1>
          <Hola message="hello" />
        </header>
        {!!this.state.title && (
          <div>
            <h3>{this.state.title}</h3>
          </div>
        )}
        <p className="App-intro">
          To get started, edit <code>src/App.js</code> and save to reload.
        </p>
      </div>
    )
  }
}
Sign up to request clarification or add additional context in comments.

8 Comments

I copied your code and got this error TypeError: Cannot read property 'result' of null: Shouldn't componentDidMount() return something?
@Mikiko9 nope. This is only a callback method with return type void. In which line error occurs?
in -> {!!this.state.result && (
@Mikiko9 I've edited the code in my answer. Please try it out.
Same error but with title instead of result. What exactly is 'this.state' referring to? Does setState bound an object called state to the class?
|
2

lukaleli is right. You should get familiar with Promises.

Another option for you would be use async & await:

async function GetApiContent() {
  let value = await fetch(api2)
  ...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.