I am new to REACT and I was trying to learn how to get and display a specific parameter from a json style message stored in an url.
For instance, the video I was trying to show, is stored in and url, which is a field of the json message itself, so it would look like this:
{
"type": "video",
"url": "http://somewebsite.com/wantedvideo.mp4"
}
From what i've read, fetch() is one way to get the data, but unfortunately I couldn't seem to understand what can be missing in the code I tried:
Here's my newbie attempt:
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.url}
</div>
)
}
}
export default App;
My render() always looked suspiciously too simple for me, so my apologies for any "mad" mistakes I may have made
PS: If instead of a video there was some other data format such as an image or plain text in the url of the url field, is there an disavantadge in using the same code to fech it?
Thank you
this.setState({
data: findresponse.url,
})
You are setting url value to data and
in render accessing the data.url. (url on data which does not exists).
If you just put {this.state.data},you will get url value.
Also, if you are getting Object from response then declare state as
this.state = {
data: {}, //instead []
}
EDIT :
e.g. to display video using video control as per comment.
<video width="400" controls>
<source src={this.state.data} type="video/mp4" />
Your browser does not support HTML5 video.
</video>
Working codesandbox
I'm going to provide a simple App component which look like this -
import React, {Component} from 'react';
import { Player } from 'video-react';
class App extends Component{
constructor() {
super();
this.state = {
data: []
}
}
componentDidMount() {
fetch('https://demo7443497.mockable.io/stream/video')
.then( resp => resp.json())
.then((data)=> {
this.setState({
data: data.url
})
})
}
render() {
return(
<Player
playsInline
src={ this.state.data }
/>
)
}
}
export default App;
Import css -
import "node_modules/video-react/dist/video-react.css"; // import css
#import "~video-react/styles/scss/video-react"; // or import scss
Add <link rel="stylesheet" href="/css/video-react.css" /> inside index.html
Try this it will work for all browsers.
Related
Good day guys, i'm having a little trouble trying to req data from axios and showing it up at ReactJS, i'm able to console.log the data, but when i try to render it at the page, it simply dot not appear, could someone please lend me a hand? i will let the code and a print of the console.log, it's probably a newbie mistake since i'm new to ReactJs and JSON, but i would be very grateful if someone could explain!
CODE:
import Image from 'next/image'
import { useRouter } from 'next/router'
import React, { Component, useState } from 'react'
import ReactDOM from 'react-dom'
import { useHistory ,useLocation } from 'react-router-dom';
import axios from 'axios'
const options = {
method: 'GET',
headers: {
'Authorization': 'OAuth oauth_consumer_key="key", oauth_signature_method="PLAINTEXT", oauth_signature="2CC8D92526EE859C90AABB1F09F3B719&"'}
};
class Page extends React.Component {
state= {
motorData: [],
opa: []
};
componentDidMount() {
const make = "fiat"
axios.get(`https://api.trademe.co.nz/v1/Search/Motors/Used.json?make=${make}`, options)
.then(res => {
const cars = res.data;
console.log(cars)
this.state.motorData.push(cars.List[0].StartPrice)
console.log(this.state.motorData)
})
}
render() {
return <div>
Data:{this.state.motorData}
</div>
}
}
export default Page ```
Thank you guys so much in advance!
Instead of doing a push to your state, you need to use setState. Something like this:
componentDidMount() {
const make = "fiat"
axios.get(`https://api.trademe.co.nz/v1/Search/Motors/Used.json?make=${make}`, options)
.then(res => {
const cars = res.data;
this.setState(state => ({
motorData: [...state.motorData, cars.List[0].StartPrice]
});
})
}
Also, your motorData is an array, right? so in your render method you might want to loop in that array because you won't be able to print it I think. You should do something like this:
render() {
return (
<div>
Data:
// Adjust the return to be what you want it to render and
// don't forget to add a `key` property to the element you
// will return
{this.state.motorData.map(data => data)}
</div>
)
}
The problem is that, to set the state correctly, you should use setState, in this way:
this.setState((state) => ({ motorData: [...state.motorData, cars.List[0].StartPrice]}))
Using setState tells React that the state is changed and it have to re-render the component.
I am trying to retrieve data from an API in React.Js but there is an small issue with the componentDidMount function.
Here is the API https://projects.cmsbox.in/app/bms/movie/public/api/upcomingMovie
I have tried this code with other API and it worked but in this case its not working. Also checked the API in Postman and everything seems to be fine.
Thanks in advance :)
import React, { Component } from 'react';
import './index.css';
import MovieCard from './moviecard'
import Homepage from './homepage';
import { render } from '#testing-library/react';
class UpcommingMovies extends Component{
constructor(props){
super(props);
this.state = {
upcmngmovie_list: [],
dataList:[],
isLoaded:false,
}
}
componentDidMount(){
fetch('https://projects.cmsbox.in/app/bms/movie/public/api/upcomingMovie')
.then(response=>response.json())
.then(data=>{
this.setState({
isLoaded:true,
dataList:data,
upcmngmovie_list:dataList,
})
});
}
render(){
var{isLoaded,upcmngmovie_list}=this.state;
function upcomngmoviecards(val){
return(
<div className="row"><MovieCard image={val.image} movie_name={val.movie_name}/></div>
);
}
if(!isLoaded){
return <div>Loading...</div>;
}
else{
return (
<>
<Homepage />
<div className="main">
<h3>Upcomming Movies</h3>
<div className="cardlist">
{upcmngmovie_list.map(upcomngmoviecards)}
</div>
</div>
</>
)
}
}
}
export default UpcommingMovies;
The api does not return an array it is returning an object. Array is in "Movie_list" property. Update your set state function to use the property.
this.setState({
isLoaded:true,
dataList:data,
upcmngmovie_list:data.Movie_list,
})
I would like to show data from a single API to different components as I want to hit the API only once and distribute the data to multiple small components. I know I can do this by using redux state but not sure how to do it. Need your help to achieve this. Below is the code done so far.
homepage/index.js
import SlidingBanner from './banner/BannerList';
import Celebslider from './celebrityslider/CelebSlider';
class HomePage extends Component {
render() {
return (
<div>
<SlidingBanner />
<anotherslider />
</div>
);
}
}
export default HomePage;
BannerList.js
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { itemsFetchData } from '../../../actions/items';
class BannerList extends Component {
componentDidMount() {
this.props.fetchData();
}
render() {
let bannerArray = [];
let banner = this.props.items.banner
for (let key in banner) {
bannerArray.push(banner[key]);
return (
<div>
<Slider {...slidersettings}>
{this.props.items.banner.map((item) => (
<div key={item.id}>
<img src={item.image_url} className="img-responsive"/>
</div>
))}
</Slider>
</div>
);
}
if (this.props.hasErrored) {
return <p>Sorry! There was an error loading the items</p>;
}
if (this.props.isLoading) {
return <p>Loading…</p>;
}
return (null);
}
}
BannerList.propTypes = {
fetchData: PropTypes.func.isRequired,
items: PropTypes.object.isRequired,
hasErrored: PropTypes.bool.isRequired,
isLoading: PropTypes.bool.isRequired
};
const mapStateToProps = (state) => {
return {
items: state.items,
hasErrored: state.itemsHasErrored,
isLoading: state.itemsIsLoading
};
};
const mapDispatchToProps = (dispatch) => {
return {
fetchData: (url) => dispatch(itemsFetchData(url))
};
};
export default connect(mapStateToProps, mapDispatchToProps)(BannerList);
anotherslider.js
Now in this file, i want to fetch another array of objects or object from the same API.
I tried to mount the API in container component but did not worked, I hope i am doing some mistake. Please correct.
If you want to fetch data in anotherslider.js file you must connect reducer to class/function inside it as well as you are making it in BannerList.js file.
Now before render call componentWillReceiveProps(nextProps) function and you will get your data here.
If you want to call data in both of the sliders, you have 2 ways to handle it.
Make your redux requests in HomePage.js component and bind the data to the other components.
When you get the data on BannerList.js component, your state will be updated. Just add the redux connection to your anotherslider.js component and get data when updated.
const mapStateToProps = (state) => {
return {
items: state.items,
hasErrored: state.itemsHasErrored,
isLoading: state.itemsIsLoading
};
};
export default connect(mapStateToProps, mapDispatchToProps)(HomeList);
Apart from all these options, you can also use react's Context API as Provider/consumer to distribute your data among small components... this will save you passing props to all small components and directly access the value in component using Context.Consumer .. moreover if you do not want to store this state in global redux store, context API will save you from it...
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;
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
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.
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:
I'm attempting to make a request to this https://www.themoviedb.org/documentation/api API in a React project and then display JSON data on my site.
I'm using Axios to make the request and I have been able to make the request and get the appropriate JSON data and console.log it or view it in the React tools in Firefox. However, I am having difficulty displaying the data in a ul. Initially I had an error pertaining to having a unique key for each list item, and I have since resolved that (or so I believe).
Here's my request and how I am attempting to render the data:
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import axios from "axios";
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
posts: []
}
}
componentDidMount() {
axios.get(`https://api.themoviedb.org/3/movie/now_playing?api_key=*apikeyhere*&language=en-US&page=1`)
.then(res => {
const posts = res.data.results.map(obj => [obj.title, obj.overview]);
this.setState({ posts });
});
}
/* render() {
return (
<div>
<h1>Movie API data</h1>
<ul>
{this.state.posts.map(post =>
<li key={post.toString()}>{post.title}</li>
)}
</ul>
</div>
);
}
}
*/
render() {
return (
<ul>
{this.state.posts.map(function(post, index){
return (
<div key={index}>
<h1>{post.title}</h1>
<p>{post.overview}</p>
</div>
)
}
)}
</ul>
);
}
}
As you can see I attempted multile approaches to rendering this. What's wrong with my code and why isn't the JSON data rendering in the ul on my site?
I think, you have an error inside success fuction ({title: obj.title, overview: obj.overview})
componentDidMount() {
axios.get(`https://api.themoviedb.org/3/movie/now_playing?api_key=*apikeyhere*&language=en-US&page=1`)
.then(res => {
const posts = res.data.results.map(obj => ({title: obj.title, overview: obj.overview}));
this.setState({ posts });
});
}