OhWords
OhWords

Reputation: 87

REACT - How to display the text contained in an url

The question is not as easy as it sounds, but I couldn't find a way to cover it fully without probably confusing the readers

I have a json message stored in an url, which has an url field itself.

So it would look something like this:

{ "type": "text", "url": "http://pastebin.com/raw/1U5vhVzH" }

Inside that url, there is the content I want to display, which is in this case, simple text

With my code, I can already obtain the pastebin url, but now I can't seem to find a way to display it's content.

If it was an image, it would be easy since I could use <img src = {pastebinURL} to get what's inside that json field url, How can I replicate the same behaviour for the text?

Here's my code so far (currently only printing the json field url):

import React, {Component} from 'react';

class App extends Component{
  constructor()
  {
    super();
    this.state={
      data: [],
    }
  }

  componentDidMount()
  {
    fetch('https://demo7443497.mockable.io/stream/text')
    .then((response) => response.json())
    .then((findresponse)=>{
      console.log(findresponse.url)
      this.setState({
        data:findresponse.url,
      })
    })
  }

  render()
  {
    return(
        <div>

        <p> Below there should be some lorem ipsum text: </p>
        <p> {this.state.data} </p>



        </div> 
    )
  }

}

export default App;

Also if it is not asking too much, I attempted to display a video as well in the exact same way (this json url fiel contains a video instead of text) but for some reason It is only displaying a greyed out video with no content, like it wasn't recognizing the variable I am passing. Did I miss any obvious detail?

Here's my very similar code for displaying the video:

import React, {Component} from 'react';

class App extends Component{
  constructor()
  {
    super();
    this.state={
      data: [],
    }
  }

  componentDidMount()
  {
    fetch('https://demo7443497.mockable.io/stream/video')
    .then((response) => response.json())
    .then((findresponse)=>{
      console.log(findresponse.url)
      this.setState({
        data:findresponse.url,
      })
    })
  }

  render()
  {
    return(
        <div>


          <video width="400" controls>
          <source src={this.state.data} type="video/mp4" />

          </video>


        </div> 
    )
  }

}

export default App;

Upvotes: 3

Views: 9358

Answers (3)

Carloluis
Carloluis

Reputation: 4320

You need to re-fetch your inner url in order to retrieve the text:

import React, { Component } from 'react';

class App extends Component {
  constructor() {
    super();
    this.state = { data: '' }; // set data to string instead of an array
  }
  componentDidMount() {
    fetch('https://demo7443497.mockable.io/stream/text')
      .then(response => response.json())
      .then(findresponse => fetch(findresponse.url, { mode: 'no-cors' })) // re-fetch
      .then(textResp => textResp.text()) // assuming this is a text
      .then(data => {
        this.setState({ data });
      });
  }
  render() {
    return (
      <div>
        <p> Below there should be some lorem ipsum text: </p>
        <p> {this.state.data} </p>
      </div>
    );
  }
}

In other cases (images, video) should be the similar. Always need to re-fetch the inner url and decide how to process / display final data depending of the type (assuming you can always know)

I just checked your video example and it is a simpler scenario, because findresponse.url (the initial response) has already the resource (image, video) and there is no need to re-fetch. But, need to change your state.data initialization to an empty string instead of an array to prevent in the first render to initialize the video resource with an empty array. This also could be solved with a spinner.

Keep in mind whenever retrieving resources from server is important to display consistent data, consider a spinner while waiting for the image or video resource, etc.

You need to be careful with all the content you are retrieving, I assume probably you will fetch from another domain. Read about CORS.


Test case:

Local test

Upvotes: 0

fila90
fila90

Reputation: 1459

text:

import React, {
  Component
} from 'react';

class App extends Component {
  constructor() {
    super();
    this.state = {
      data: '',
    }
  }

  componentWillMount() {
    fetch('https://demo7443497.mockable.io/stream/text')
      .then((response) => response.json())
      .then((response) => {
        // now fetch the text
        fetch(response.url)
          .then(response2 => response2.text())
          .then(response2 => {
            this.setState({
              data: response2
            })
          })
      })
  }

  render() {
    return (
      <div>
        <p> Below there should be some lorem ipsum text: </p>
        <p> {this.state.data} </p>
      </div> 
    )
  }
}
export default App;

video:

import React, {
  Component
} from 'react';

class App extends Component {
  constructor() {
    super();
    this.state = {
      data: ''
    }
  }

  componentDidMount() {
    fetch('https://demo7443497.mockable.io/stream/video')
      .then((response) => response.json())
      .then((findresponse) => {
        console.log(findresponse.url)
        this.setState({
          data: findresponse.url,
        })
      })
  }

  render() {
    return (
      <div>
      {this.state.data
       ?
       <video width="400" controls>
        <source src={this.state.data} type="video/mp4" />
      </video>
      : null}          
      </div> 
     )
  }
}
export default App;

don't set your state to an array then cast it to string, make it an empty string on the start. your video example is not working because on first render video is initialized with this.state.data which is an empty array, changing that to a string won't reinitialize video so you need that if statement there hope it helps :D

Upvotes: 2

Bk Santiago
Bk Santiago

Reputation: 1573

If it's a URL, then will re-fetching it works?

  componentDidMount()
  {
    fetch('https://demo7443497.mockable.io/stream/text')
    .then((response) => response.json())
    .then((findresponse)=>{
      console.log(findresponse.url)
      fetch(findresponse.url)
        .then((urlResp) => urlResp.text())
        .then((response) => {
            this.setState({
              data:findresponse.url,
            });
          });
    });
  }

For the video, have tried opening the actual URL on a browser (i.e. Chrome) to check if it's a valid mp4, chrome should be able to easily read it.

Upvotes: 0

Related Questions