Display API data using Axios and a list in React - json

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 });
});
}

Related

Cannot read property 'map' of undefined in React + Phoenix framework

I'm new to React. I have provided Postgresql API and I want to add those data in Material UI Table.
I've made some mistakes and I'm unable to figure to out.
I'm using API calls for the first time using Axios. So please guide me to solve this issue.
I'm using React.js for frontend work, Phoenix framework for backend, and PostgreSQL database.
The below component is used to handle API request using Axios
import axios from "axios"
import MedicineCard from './MedicineCard'
class Medicines extends React.Component {
constructor() {
super();
this.state = { medicines: [] };
}
componentWillMount() {
axios.get('http://localhost:4000/medicines')
.then(response => {
this.setState({ medicines: response.data.medicines });
})
.catch(error => {
console.log(error);
});
}
render() {
const posts = this.state.medicines.map((medicine, index) =>
<MedicineCard
key = { index }
medid = {medicine.medid}
medname = {medicine.medname}
/>
)
return (
<div>
{posts}
</div>
)
}
}
export default Medicines
Below Component is used for Material UI Table
import React from 'react'
import MaterialTable from 'material-table'
class MedicineCard extends React.Component{
render(){
const data=[
{medid:this.props.medid,medname:this.props.medname}
]
const column=[
{
title:'Medicine_ID',field:'medid'
},
{
title:'Medicine_Name',field:'medname'
}
]
return (
<div>
<MaterialTable title="Material Table"
data={data}
column ={column}
/>
</div>
);
}
}
export default MedicineCard
This component is used to display UI
import React from 'react'
import Medicines from './Medicines'
const Test = () => (
<div>
<Medicines />
</div>
)
export default Test
Please help me and guide me out to solve this issue

Data not appearing after axios fetch (ReactJs)

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.

How retrieve data from an API in JSON to a list in React.Js

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,
})

Get JSON Data in multiple components using reactjs and redux

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...

Understanding React.JS JSON feed and how to parse

I've got the following code which is looping through an JSON file from an API and loops through some posts.
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
//https://alligator.io/react/axios-react/
import axios from 'axios';
export default class PostList extends React.Component {
state = {
posts: []
}
componentDidMount() {
axios.get(`https://jsonplaceholder.typicode.com/users`)
.then(res => {
const posts = res.data;
this.setState({ posts });
})
}
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
<p className="App-intro">
Pulls in post slugs from Domain
</p>
<ul>
{ this.state.posts.map(post => <li>{post.name} - {post.username} </li>)}
</ul>
</div>
)
}
}
This works fine, and gets the information which was needed.
Now, in my test JSON file, the format is as follows:
https://jsonplaceholder.typicode.com/users
But in my actual JSON file from WordPress Rest API, we have another item, named core_layout:
JSON image
My issue is, trying to use the same code such as {post.name}does not get the information needed such as core_layout->image->name.
Is there an easy way around this?
Thanks all!
EDIT:
Tried the answers below, but still no luck, get the error TypeError: Cannot read property 'map' of undefined:
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
//https://alligator.io/react/axios-react/
import axios from 'axios';
export default class PostList extends React.Component {
state = {
posts: [],
coreLayout: {}
}
componentDidMount() {
axios.get(`https://jsonplaceholder.typicode.com/users`)
.then(res => {
// const posts = res.data;
//this.setState({ posts });
const { posts, core_layout: coreLayout } = res.data;
this.setState({ posts, coreLayout });
})
}
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
<p className="App-intro">
Pulls in post slugs from domain
</p>
<ul>
{ this.state.posts.map(post => <li>{post.name} - {post.core_layout.image.name}</li>)}
</ul>
</div>
)
}
}
EDIT 2:
Tried the below: This gets the title, but again, not the actual corelayout I need.
import React, { Component } from 'react';
class App extends Component {
constructor() {
super();
this.state = {
movies: []
}
}
componentDidMount() {
let dataURL = "http://zinsseruk.com/wp-json/wp/v2/posts?per_page=1";
fetch(dataURL)
.then(res => res.json())
.then(res => {
this.setState({
movies: res
})
})
}
render() {
let movies = this.state.movies.map((movie, index) => {
return <div key={index}>
<p><strong>Title:</strong> {movie.title.rendered}</p>
<p><strong>Title:</strong> {movie.core_layout.acf_fc_layout}</p>
</div>
});
return (
<div>
<h2>Star Wars Movies</h2>
{movies}
</div>
)
}
}
export default App;
Replace const posts = res.data; with const posts = res.data.core_layout;. Then you'll get an array similar to what you have in your test file.
I think you need to understand the JSON structure you receive from the API. Where is located core_layout property? Inside each post property as a children?
So in the posts loop you can use post.core_layout.image.name for image name, for example (and so on with other properties).
If core_property is at the root of the data you receive, you can load it inside your state like so:
state = {
posts: [],
coreLayout: {}
}
componentDidMount() {
axios.get(`https://jsonplaceholder.typicode.com/users`)
.then(res => {
// This is equivalent of doing
// const posts = res.data.posts
// const coreLayout = res.data.core_layout
const { posts, core_layout: coreLayout } = res.data;
this.setState({ posts, coreLayout });
})
}
Then use it in your code by using local component state:
render() {
...
// For example image name:
console.log('image name', this.state.coreLayout.image.name)
...
}