daydreamer
daydreamer

Reputation: 91969

How to load content for external URL in React?

I am trying to build RSS reader where there are a bunch of URLs and clicking on one of them loads the content for the selected content.

My attempt looks like

import React from "react";
import Listings from "./listings"
import Content from "./content"

const urls = [
  "https://www.washingtonpost.com/news/the-switch/wp/2017/10/17/googles-pixel-2-gives-you-the-best-of-android-if-you-can-find-it/?utm_term=.dacb8f419a4b",
  "https://arstechnica.com/gadgets/2017/10/windows-10-fall-creators-update-lots-of-small-changes-and-maybe-the-revolution/",
  "https://www.theverge.com/2017/10/17/16481628/microsoft-surface-book-2-price-release-date-specs-availability-processor"
];

export default class RSS extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      selectedUrl: urls[0],
      urls: urls,
      content: "TBD"
    }
  }

  onUrlSelect = (e, url) => {
    e.preventDefault();
    //console.log("selected Url Index: ", url);
    this.setState({selectedUrl: url});

  }

  componentWillMount() {
    this.loadData(this.state.selectedUrl);
  }

  loadData = (url) => {
    fetch(url)
      .then(function (response) {
        console.log(url + " -> " + response.ok);
        return response.body;
      })
      .then(function (data) {
        console.log("data: ", data);
        this.setState({ content: data });
      }.bind(this))
      .catch(function (err) {
        console.log("failed to load ", url, err.stack);
      });
  }

  render() {
    return (
      <div>
        <Listings urls={this.state.urls} onUrlSelect={this.onUrlSelect}/>
        <Content data={this.state.data}/>
      </div>
    )
  }
}  

Where Content looks like

import React from "react";

export default function Content(props) {
  return (
    <div>
      <p> Loading: {props.data} </p>
    </div>
  );
}

When I try to load it, Nothing prints out. However, on the Developer Tools > Console, I see

data:  ReadableStream {}locked: (...)__proto__: Object
index.js? [sm]:35  

My code is available on https://codesandbox.io/s/wkwm8z3xl

I am not sure what I am doing wrong, any help is highly appreciated. Thanks

update
I changed my code to read response.text() and then on the view I did the following

export default function Content(props) {
  return (
    <div>
      <div dangerouslySetInnerHTML={{__html: props.data}}/>
    </div>
  );
}

as recommended in https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml

However, the page the results as output is not exactly how it should be
enter image description here

The code is updated at https://codesandbox.io/s/wkwm8z3xl
This is happening because the other assets like css, images are not fetched.

How can I fix this?

Upvotes: 2

Views: 26956

Answers (2)

Robert.T
Robert.T

Reputation: 81

You should use response.text() method to reads content.

See https://developer.mozilla.org/en-US/docs/Web/API/Response

loadData = (url) => {
  fetch(url)
    .then(function (response) {
      // console.log(url + " -> " + response.ok);
      if(response.ok){
        return response.text();
      }
      throw new Error('Error message.');
    })
    .then(function (data) {
      console.log("data: ", data);
      this.setState({ content: data });
    }.bind(this))
    .catch(function (err) {
      console.log("failed to load ", url, err.message);
    });
}

Upvotes: 0

Nicholas Tower
Nicholas Tower

Reputation: 85012

return response.body

This line doesn't actually give you the data in the body. To get access to the data in the body, you'll need to use one of a couple functions. It looks like the data you're getting back is just a text file, so you'll want to do return response.text(). You can read more about extracting the body from Fetch here: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Body

One other thing you'll need to fix is that when you call setState, you're setting the data onto state.content, but then in your render function you're expecting it to be on this.state.data. One or the other will need to change.

Upvotes: 2

Related Questions