4

I've been pulling my hair out too long and I can't focus anymore.

I am trying to take the json from a url and just render it visually in the browser. It doesn't even need to be formatted, at least it doesn't until I get past this hurdle.

I can get it to show up in the console via console.log, but I can't seem to get the response into the render method. I've simplified it down to the code below until I can see something on the page.

import React, { Component } from 'react';
// import axios from 'axios';

var co = require('co');
co(function *() {
var res = yield fetch('https://api.stackexchange.com/2.2/search?order=desc&sort=activity&intitle=perl&site=stackoverflow');
var json = yield res.json();
console.log(res);
});

class App extends Component {

render() {
return (
  <div className="App">
    INSERT JSON HERE
  </div>
  );
 }
}

export default App;

I have also retrieved the response using

fetch('https://api.stackexchange.com/2.2/search?order=desc&sort=activity&intitle=perl&site=stackoverflow')
    .then(function(res) {
        return res.json();
    }).then(function(json) {
        console.log(json);
    });

I originally started by using axios because I thought "oh man, I'm going to use axios because who's awesome? I'm awesome."

axios.get('https://api.stackexchange.com/2.2/search?order=desc&sort=activity&intitle=perl&site=stackoverflow')
  .then(function(response) {
    console.log(response.data);
  });

but that was a fallacious because today I am not awesome.

I'll take whatever help I can get! My original plans also included using map to just iterate over the "items" so extra points if you can steer me closer to salvation in that area.

fearofmusic
  • 155
  • 1
  • 1
  • 9
  • I'm not sure I see the problem. What's wrong with using `{}` and inserting it inside the div? – Andrew Li Apr 30 '17 at 23:19
  • Everything I have tried to put inside curly braces inside the render method has thrown an error. Usually some kind of "that thing is not defined" error. – fearofmusic Apr 30 '17 at 23:31
  • `axios.get('https://api.stackexchange.com/2.2/search?order=desc&sort=activity&intitle=perl&site=stackoverflow') .then(function(response) { console.log(response.data); }).catch(function(e){console.log(e)})` what is the output of this? – kurumkan Apr 30 '17 at 23:34
  • @luskmonster Because your response doesn't exist outside the callback! Assign it to a class property or save it into state... – Andrew Li Apr 30 '17 at 23:35
  • @ArslArsl `Object { items: Array[30], has_more: true, quota_max: 300, quota_remaining: 291 } bundle.js:32919:10 Error: Objects are not valid as a React child (found: object with keys {items, has_more, quota_max, quota_remaining}). If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons. Check the render method of `App`. bundle.js:11488:16` – fearofmusic May 01 '17 at 00:20

2 Answers2

5
import React, { Component } from "react";
import axios from "axios";

const URL = "https://api.stackexchange.com/2.2/search?order=desc&sort=activity&intitle=perl&site=stackoverflow";

export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      items: []
    }
  }

  componentDidMount() {
    var _this = this;
    axios.get(URL)
    .then(function(res){
      _this.setState({
        items: res.data.items
      });
    })
    .catch(function(e) {
      console.log("ERROR ", e);
    })
  }

  render() {
    const renderItems = this.state.items.map(function(item, i) {
      return <li key={i}>{item.title}</li>
    });

    return (
      <ul className="App">
        {renderItems}
      </ul>
    );
  }
}
kurumkan
  • 2,256
  • 3
  • 19
  • 51
3

You can accomplish this via React's Component State and Lifecycle.

Read about this here: React State/Lifecycle

You can place the Fetch call in the component's componentDidMount function, and have the callback set the state for viewing.

If you were to use Fetch, your component may look like this:

class App extends Component {
 constructor(props) {
  super(props);
  this.state = {
   data: false
  };
  this.receiveData = this.receiveData.bind(this);
 }
 componentDidMount() {
  var _self = this;
  fetch('https://api.stackexchange.com/2.2/search?order=desc&sort=activity&intitle=perl&site=stackoverflow')
  .then(function(res) {
     return res.json();
  }).then(function(json) {
     console.log(json);
     _self.receiveData(json);
  });
 }
 receiveData(data) {
  this.setState({data});
 }
 render() {
  return <div>{this.state.data}</div>
 }
}
Michael Lyons
  • 554
  • 3
  • 9
  • 1
    This definitely seems like where I was trying to go, I get the error below in the console when I try to run this tho. `Error: Objects are not valid as a React child (found: object with keys {items, has_more, quota_max, quota_remaining}). If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons. Check the render method of 'App'.` – fearofmusic May 01 '17 at 00:25
  • Oh shoot, yeah sorry Objects can't be rendered directly in a react element. If you just want to see the data you can ```
    JSON.stringify(this.state.data)
    ``` to print it as a string for output.
    – Michael Lyons May 01 '17 at 00:32
  • I can see something! – fearofmusic May 01 '17 at 00:51
  • Nice! Now that the object is in your state, you can pass it to props of children and do w/e else you want with it! – Michael Lyons May 01 '17 at 00:59