Undefined object in react js - reactjs

I'm getting the following error:
Uncaught ReferenceError: videos2 is not defined
In this app:
class App extends Component {
constructor(props) {
super(props)
this.state = {
videos2:[],
selectedVideo:null
}
this.DMSearch()
}
DMSearch(){
fetch("https://api.dailymotion.com/videos?fields=description,id,thumbnail_url,title,&limit=5&search=cars")
.then(response => response.json())
.then(data=>this.setState({
videos2:data.videos2,
selectedVideo:videos2[0]}))
console.log(videos2)
}
render () {
const {videos2}=this.state
return (
<div>
<SearchBar onSearchTermChange= {DMSearch}/>
<VideoDetail video={this.state.selectedVideo}/>
<VideoList
onVideoSelect={selectedVideo=>this.setState({selectedVideo})}
videos2={this.state.videos2}/>
</div>
)
}
}
Therefore Im wondering where should I define videos2 apart from where it is defined already. Anyone could point me out to the part of the component that might be causing the error?
EDIT: Actually it had to do with the way api json was shaped.
This is the proper way to fetch the list from json:
this.setState({
videos2: videos2.list,
selectedVideo: videos2[0]
});

In DMSearch function there is no videos2 variable defined. You probably want:
.then(data => {
this.setState({
videos2: data.videos2,
selectedVideo: data.videos2[0]
});
console.log(data.videos2);
});
or
.then(data => {
const { videos2 } = data;
this.setState({
videos2,
selectedVideo:videos2[0]
});
console.log(videos2);
});

In DMSearch, videos2 is undefined.
DMSearch() {
fetch("https://api.dailymotion.com/videos?fields=description,id,thumbnail_url,title,&limit=5&search=cars")
.then(response => response.json())
.then(data => {
let videos2 = data.videos2; //define it here
this.setState({
videos2: videos2,
selectedVideo: videos2[0] // <-- this line will throw error
})
})
console.log(videos2) // <-- and this too
}

Related

Using this.setstate with Fetch API

I'm trying to use a fetch call to retrieve some API data. Unfortunately I cannot use this to set the state.
consructor() {
this.state = {
weather: ""
};
this.search = this.search.bind(this);
}
search(postalCode) {
const url = `https://api.weatherbit.io/v2.0/forecast/daily?&postal_code=${postalCode}&key=${API_KEY}&days=7`;
fetch(url)
.then(response => response.json())
.then(data => console.log(data));
}'
This code works fine, and prints an object to the console containing the correct data.
consructor() {
this.state = {
weather: ""
};
this.search = this.search.bind(this);
}
search(postalCode) {
const url = `https://api.weatherbit.io/v2.0/forecast/daily?&postal_code=${postalCode}&key=${API_KEY}&days=7`;
fetch(url)
.then(response => response.json())
.then(data => this.setState({weather: data}))
.catch(error => console.log(error));
}
As soon as I try to use the data to update my state, I get the "this.setState is not a function" error. I've bound the search function in the constructor.
I've even tried to bind it like this:
fetch(url)
.then(response => response.json())
.then(data => this.setState({ weather: data })).bind(this);
This doesn't work either. Anyone have any ideas?
I can't see your class definition, but I believe that using the state requires you to extend Component
The issue you are getting is that this component doesn't have the state functions in it.
Here's some code from a working project of mine using similar fetches, returned by the services:
type HomeProps = {}
type State = {
projects: ProjectModel[],
skills: SkillModel[],
resume: JobModel[]
}
export default class Home extends Component<HomeProps, State> {
private projectService: ProjectService;
constructor(props: HomeProps) {
super(props);
this.projectService = new ProjectService();
this.state = {
projects: []
}
}
componentDidMount() {
this.getProjects();
}
private getProjects() {
this.projectService.retrieveItems().then(projects => {
this.setState({projects});
})
}
Here is the service:
export default class ProjectService {
url = "http://api.flynndev.us";
async retrieveItems() {
return fetch(`${this.url}/projects/all`)
.then(response => response.json());
}
async getItem(itemLink: string) {
return fetch(`${this.url}/projects/${itemLink}`)
.then(response => response.json());
}
}
Note: I'm using Typescript. Feel free to ignore the typing stuff for regular React

Unable to access Api call data. Returns undefined. React

I am trying to make a movie search app with React and have made an API call to The Movie Database API. What I am trying to do is get the data of the new movie releases, but then make another API call to get the specific details for each of those new releases since that data is stored in a different location.
I am able to access the data from the first API call, but when I try to access the movie taglines from the second data object, the console outputs "Cannot read property 'tagline' of undefined".
App.js
class App extends Component {
constructor(props) {
super(props)
this.state = {
movieRows: [],
ids: [],
movieDetails: [],
}
this.performSearch = this.performSearch.bind(this);
}
componentDidMount() {
this.performSearch();
}
performSearch() {
const urlString = "https://api.themoviedb.org/3/movie/popular?api_key=6db3cd67e35336927891a72c05&language=en-US&page=1";
axios.get(urlString)
.then(res => {
const results = res.data.results
let movieRows = [];
let movieDetails = [];
results.forEach((movie) => {
movieRows.push(movie);
axios.get(`https://api.themoviedb.org/3/movie/${movie.id}?api_key=6db3cd67e35336927891a72c05&language=en-US`)
.then(res => {
movieDetails.push(res.data);
})
.catch(function (error) {
console.log(error);
});
});
this.setState({
movieRows: movieRows,
movieDetails: movieDetails,
});
})
.catch(function (error) {
console.log(error);
});
}
Content.js
export default class Content extends Component {
constructor(props) {
super(props)
this.state = {
name: 'Jonathan',
}
this.filmLoop = this.filmLoop.bind(this);
}
filmLoop() {
let movieData = this.props.globalState.movieRows;
let movieDetails = this.props.globalState.movieDetails;
return movieData.map((movie, index) => {
return (
<div className="film" key={index}>
<img className="poster" src={`http://image.tmdb.org/t/p/w342${movie.poster_path}`} alt="The Dark Knight poster" />
<div className="film-info">
<div className="film-title">
<h3>{movie.title}</h3>
</div>
<h4>{movieDetails[index].tagline}</h4>
*I get the error from the last line
Well the main issue is that you are calling setState outside your .then you have to update the state inside your then or your catch. This is because the promise is an async function, so you have to change the state only when the promise has been resolved of rejected.
performSearch() {
const urlString = "https://api.themoviedb.org/3/movie/popular?api_key=6db3cd67e35336927891a72c05&language=en-US&page=1";
axios.get(urlString)
.then(responsePopular => {
const results = responsePopular.data.results
let movieRows = [];
let movieDetails = [];
results.forEach((movie) => {
movieRows = [...movieRows, movie];
axios.get(`https://api.themoviedb.org/3/movie/${movie.id}?api_key=6db3cd67e35336927891a72c05&language=en-US`)
.then(responseMovie => {
movieDetails = [...movieDetails, responseMovie.data];
this.setState({
movieRows: movieRows,
movieDetails: movieDetails,
})
})
.catch(function (error) {
console.log(error);
});
});
})
.catch(function (error) {
console.log(error);
});
}
I think that this could solve your issue.

React doesn't render data coming from an api response

I've seen a lot of questions and I couldn't get the solution
here is my code:
import React, { Component } from "react";
import axios from "axios";
import "./tree.css";
import "./mainTree";
class TablesTree extends Component {
constructor(props) {
super(props);
this.data = this.props.info;
this.state = {
fields: [],
data: [],
show: false
};
}
componentDidMount() {
var dataGet = [];
this.props.tables.forEach((name, i) => {
this.getFieldsTable(name.TABLE_NAME, (err, res) => {
if (res) {
dataGet.push({
TABLE_NAME: name.TABLE_NAME,
columns: res
});
}
});
});
this.setState({ data: dataGet });
}
getFieldsTable(table, callback) {
axios
.get(`table/columns?name=${this.data.user}&psw=${this.data.password}&schema=${this.data.schema}&table=${table}`)
.then(response => {
callback(null, response.data);
})
.catch(error => {
console.log(error);
});
}
render() {
return (
<div>
{this.state.data
? this.state.data.map((itm, i) => {
return (
<div>
<h1>{itm.TABLE_NAME}</h1>
</div>
);
})
: null}
</div>
);
}
}
export default TablesTree;
I've made console.log of the this.state.data
and the data is in there, but it doesn't renders anything
I've tried a lot of soutions, but I still without rendering the data, I will apreciate your help.
There's a few things I would change about your code, but most importantly you need to do this.setState after your push to dataGet (inside of your callback function).
Because your API call is asynchronous, you are only calling setState once when your component is initially mounted (and while dataGet is still empty).
getFieldsTable is asynchronous, so the dataGet array will be empty when you call setState.
You could return the promise from getFieldsTable and use Promise.all on all the promises, and use the data when all of them have resolved.
Example
class TablesTree extends Component {
// ...
componentDidMount() {
const promises = this.props.tables.map(name => {
return this.getFieldsTable(name.TABLE_NAME).then(res => {
return {
TABLE_NAME: name.TABLE_NAME,
columns: res
};
});
});
Promise.all(promises).then(data => {
this.setState({ data });
});
}
getFieldsTable(table) {
return axios
.get(`table/columns?name=${this.data.user}&psw=${this.data.password}&schema=${this.data.schema}&table=${table}`)
.then(response => {
return response.data;
})
.catch(error => {
console.log(error);
});
}
// ...
}

TypeError: this.state.patients.map is not a function

i am new in react js,and i am learning to create a React application and I got a problem with mapping function:
Here's my request and how I am attempting to render the data:
class Patients extends Component {
constructor(props) {
super(props)
this.state = {
patients: []
}
}
componentDidMount() {
api.getPatients()
.then( patients => {
console.log( patients)
this.setState({
patients: patients
})
})
.catch(err => console.log(err))
}
render() {
return (
<div className=" Patientss">
<h2>List of Patient</h2>
{this.state.patients.map((c, i) => <li key={i}>{c.name}</li>)}
</div>
);
}
}
export default Patients;
here my api calling
import axios from 'axios';
const service = axios.create({
baseURL: process.env.NODE_ENV === 'production' ? '/api' : 'http://localhost:3000/patient',
});
const errHandler = err => {
console.error(err);
throw err;
};
export default {
service: service,
getPatients() {
return service
.get('/')
.then(res => res.data)
.catch(errHandler);
},
}
and I get the following error:
TypeError: this.state.patients.map is not a function
i've try to use slice aswell but it didnt work, anyone know whats wrong with my code?`
Based on the symptoms (heh), the patients object you get in api.getPatients() isn't an array.
console.log() it to see what it actually is.
EDIT: Based on the comments, the patients object looks like
{
count: 24,
patient: [...],
}
so the this.setState() call needs to be
this.setState({patients: patients.patient})
You can also do something like this as an conditional rendering. It will check that if this.state.patient exists then only it will go ahead and call this.state.patients.map function. It will also ensure that you don't receive any errors later on due to bad responses.
I updated your Patients Code example.
class Patients extends Component {
constructor(props) {
super(props)
this.state = {
patients: []
}
}
componentDidMount() {
api.getPatients()
.then( patients => {
console.log( patients)
this.setState({
patients: patients
})
})
.catch(err => console.log(err))
}
render() {
return (
<div className=" Patientss">
<h2>List of Patient</h2>
{ this.state.patients && this.state.patients.map((c, i) => <li key={i}>{c.name}</li>)}
</div>
);
}
}
export default Patients;
I hope it helps. Thanks!!

React Multiple Fetch from state

so I am trying to fetch my SWAPI json-server twice using the homeworld id to get the homeworld name but I just get "TypeError: Cannot read property 'name' of undefined". Im fairly new to React so if it looks messy im sorry! Thanks in advance!
import React, { Component } from 'react';
import './Card.css';
const person = personID =>
`http://localhost:3008/people/${personID}`
const picture = pictureID =>
`http://localhost:3008/${pictureID}`
// const planet = planetID =>
// `http://localhost:3008/planets/${planetID}`
class Card extends Component {
constructor(props){
super(props);
this.state ={
requestFailed: false,
person: 1,
planet: 4
}
}
componentDidMount(){
fetch(person(this.state.person))
.then(response => {
if(!response.ok) {
throw Error("Network Request Failed");
}
return response
})
.then(d => d.json())
.then(d => {
this.setState({
cardData: d
})
}, () => {
this.setState({
requestFailed: true
})
})
fetch(`http://localhost:3008/planets/${this.state.cardData.homeworld}`)
.then(data => data.json())
.then(data => {
this.setState({
homeData: data
})
})
}
render() {
if(this.state.requestFailed === true) return <p>Error please try
again!</p>
if(!this.state.cardData) return <p>Loading ...</p>
return (
<div className='card'>
<div className='card-content'>
<div className='card-name'>{this.state.cardData.name}</div>
<img src={picture(this.state.cardData.image)}
alt='profile'/>
<p>
<span>Birthday:</span>
<span>{this.state.cardData.birth_year}</span>
</p>
<p>
{/* Note that in order to get the homeworld's name, you have to get the planet name from a different endpoint than the people */}
<span>Homeworld:</span>
<span>{this.state.homeData.name}</span>
</p>
</div>
</div>
);
}
}
export default Card;
It looks like the first problem is that you're attempting to render homeData.name before it's loaded. You should probably have a loading check similar to the cardData loading check. Or you could just render nothing until it's loaded:
{this.state.homeData ?
<span>{this.state.homeData.name}</span> :
<span>Loading...</span>
}
The 2nd problem is that you're doing the second fetch of homeData at the same time as the first fetch. So this line:
fetch(`http://localhost:3008/planets/${this.state.cardData.homeworld}`)
Will always fail because the cardData is not loaded into the state yet when it runs.
What you should do is move it inside the response part of the first request:
fetch(person(this.state.person))
.then(response => {
if(!response.ok) {
throw Error("Network Request Failed");
}
return response
})
.then(d => d.json())
.then(d => {
this.setState({
cardData: d
})
fetch(`http://localhost:3008/planets/${d.homeworld}`)
.then(data => data.json())
.then(data => {
this.setState({
homeData: data
})
})
}, () => {
this.setState({
requestFailed: true
})
})
It would help to extract these into separate functions to clean it up a bit.

Resources