So I want to call an API with react and my data is not showing up correctly I know I did it right but is there anything I am missing because I don't know why it is still showing Loading
import React from 'react';
import './App.css';
class App extends React.Component {
constructor (props) {
super(props);
this.state = {
students: [],
isLoaded: false,
error: null,
}
}
componentDidMount() {
fetch("http://localhost:3200/students")
.then(res => res.json())
.then((myresult) => {
this.setState({
isLoaded: true,
students: myresult.students,
});
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
)
}
render() {
const {error, isLoaded, students} = this.state;
if (error) {
return <div>Error: {error.message}</div>
} else if (isLoaded) {
return <div> Loading ...</div>
} else {
return (
<ul>
{students && students.map(student => (
<li key={student._id}>
{student._id} {student.role_num}
</li>
))}
</ul>
);
}
}
}
export default App;
I am trying to display information from this URL http://localhost:3200/students
I was following this link on how to call an API https://reactjs.org/docs/faq-ajax.html
hey guys updated my code I am still getting the same issue stuck on loading I don't know whether I am passing in my data properly
I think there a couple of things going on here but main points are
its componentDidMount not MountComponent
your not setting students correctly in state
In you code above for MountComponent see that you are setting up movieItems and your state is expecting students. To solve the issue use the code below.
MountComponent = () => {
fetch("http://localhost:3200/students")
.then(res => res.json())
.then((myresult) => {
this.setState({
isLoaded: true,
students: myresult.students,
});
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
)
}
change this:
} else if (!isLoaded) {
to:
} else if (isLoaded) {
Write this in your function and check
componentDidMount() {
fetch("http://localhost:3200/students").then(res => {
this.setState({ students : res.data })
})
}
Related
I am new at react and
I have been trying to apply event handling in react but facing some Problem on onclick event.
When the button "show me of germany" is called the Page then stuck to loading only ...
Here is the code i have written ..
class App extends Component {
constructor(props) {
super(props);
this.state = { articles: [],
isLoaded:false ,
country:'us'
}
this.change = this.change.bind(this);
}
componentDidMount() {
const APIurl = `https://newsapi.org/v2/top-headlines?country=${this.state.country}&apiKey=${API_KEY}`;
fetch(APIurl)
.then(response => response.json())
.then(json => {
this.setState({
articles: json.articles,
isLoaded:true
})
})
}
// function to change the state
change()
{
this.setState({
articles: [],
isLoaded:false ,
country:"de"
})
}
render() {
const { isLoaded,articles } = this.state;
if(!isLoaded)
{
return (<h1>Loading....</h1>)
}
return (
<div>
<Navbar/>
<button onClick={this.change}>show me of germany</button>
<ul>
{articles.map(item=>(
<News item={item}/>
))}
</ul>
</div>
);
}
}
export default App;
Hope you understood the problem
You have to do request again.
class App extends Component {
constructor(props) {
super(props);
this.state = {
articles: [],
isLoaded: false,
country:'us'
}
this.change = this.change.bind(this);
}
componentDidMount() {
fetchData(this.state.country);
}
componentDidUpdate(prevProps, prevState) {
const { country: prevCountry } = prevState;
const { country: nextCountry } = this.state;
if (prevCountry !== nextCountry) {
fetchData(nextCountry);
}
}
change() {
this.setState({ country: 'de' });
}
fetchData(country) {
this.setState({ articles: [], isLoaded: false });
fetch(
`https://newsapi.org/v2/top-headlines?country=${country}&apiKey=${API_KEY}`
)
.then(res => res.json())
.then(({ articles }) => {
this.setState({ articles, isLoaded: true });
})
.catch(console.error);
}
render() {
//...
}
}
export default App;
I'm trying to do a basic API fetch and show that information onClick using a button called GENERATE. All it should do for now is show the first url in the json I receive.
Once that is achieved, I want it to show the next url on each click.
App.js
import React, { Component } from 'react';
import { ThemeProvider, createToolkitTheme } from 'internaltools/theme';
import { AppHeader } from 'internaltools/app-header';
const LIGHT_THEME = createToolkitTheme('light');
const DARK_THEME = createToolkitTheme('dark');
const API = 'https://hn.algolia.com/api/v1/search?query=';
const DEFAULT_QUERY = 'redux';
class App extends Component {
constructor(props) {
super(props);
this.state = {
hits: [],
isLoading: false,
error: null,
};
}
componentDidMount(){
this.setState({ isLoading: true });
fetch(API + DEFAULT_QUERY)
.then(response => {
if (response.ok) {
return response.json();
} else {
throw new Error('Something went wrong with the API...');
}
})
.then(data => this.setState({ hits: data.hits[0], isLoading: false }))
.catch(error => this.setState({ error, isLoading: false }));
}
render() {
const { hits, isLoading, error } = this.state;
return (
<>
<button onClick={hits.url}>GENERATE</button>
</>
);
}
}
Please help me find out why my button doesn't work. And how do I iterate over the urls on each click, i.e. show the next url from the json on each click. Thanks.
You should pass a function name to your onClick handler. Then in that function you can access the data you wanted.
enter code here
import React, { Component } from 'react';
import { ThemeProvider, createToolkitTheme } from 'internaltools/theme';
import { AppHeader } from 'internaltools/app-header';
const LIGHT_THEME = createToolkitTheme('light');
const DARK_THEME = createToolkitTheme('dark');
const API = 'https://hn.algolia.com/api/v1/search?query=';
const DEFAULT_QUERY = 'redux';
class App extends Component {
constructor(props) {
super(props);
this.state = {
hits: [],
isLoading: false,
error: null,
hitsCount: 0
};
this.handleClick = this.handleClick.bind(this);
}
componentDidMount(){
this.setState({ isLoading: true });
fetch(API + DEFAULT_QUERY)
.then(response => {
if (response.ok) {
return response.json();
} else {
throw new Error('Something went wrong with the API...');
}
})
.then(data =>
this.setState({ hits: data.hits, hitsCount: 0 ,isLoading: false
}))
.catch(error => this.setState({ error, isLoading: false }));
}
handleClick(){
this.setState(prevState => ({ hitsCount: prevState.hitsCount + 1
}));
}
render() {
const { hits, hitsCount, isLoading, error } = this.state;
return (
<>
<div>
count: {hitsCount}
url: {hits[hitsCount].url}
</div>
<button onClick={this.handleClick}>GENERATE</button>
</>
);
}
}
You need to pass an onClick handler function to update a state value.
Here's a codesandbox that stores the hits array in state along with a current index, and a handler that simply increments the index.
Consider This:
Read through the comments in the code to get the updates.
class App extends Component {
constructor(props) {
super(props);
this.state = {
hits: [],
currentHit: 0, //add a state currentHit to hold the url that is displayed by now
isLoading: false,
error: null,
};
}
componentDidMount(){
this.setState({ isLoading: true });
fetch(API + DEFAULT_QUERY)
.then(response => {
if (response.ok) {
return response.json();
} else {
throw new Error('Something went wrong with the API...');
}
})
.then(data => this.setState({ hits: data.hits, isLoading: false })) //Make hits array holding all the hits in the response instead of only the first one
.catch(error => this.setState({ error, isLoading: false }));
}
handleClick = () => {
this.setState(prevState => ({
currentHit: prevState.currentHit + 1,
}));
}
render() {
const { hits, isLoading, error, currentHit } = this.state;
// pass the handleClick function as a callback for onClick event in the button.
return (
<>
<p>{hits[currentHit].url}<p/>
<button onClick={this.handleClick.bind(this)}>GENERATE</button>
</>
);
}
}
Here is the working code, on each click next url will be shown.
codesandbox link
handleChange method can work if you want to append the url from array as well. Or you could just increment the index in this function.
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
class App extends React.Component {
state = {
data: [],
index: 0
};
componentDidMount() {
this.setState({ isLoading: true });
fetch("https://reqres.in/api/users")
.then(response => {
if (response) {
return response.json();
} else {
throw new Error("Something went wrong with the API...");
}
})
.then(data => this.setState({ data: data.data }))
.catch(error => this.setState({ error }));
}
handleChange = () => {
let i =
this.state.index < this.state.data.length ? (this.state.index += 1) : 0;
this.setState({ index: i });
};
render() {
return (
<div className="App">
<span>
{this.state.data.length && this.state.data[this.state.index].avatar}
</span>
<button onClick={this.handleChange}>GENERATE</button>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Please help me with this
I just learn about ReactJs and now I learn about get data from Api, before that i use fetch to get api and it normal but when i use Axios and have that problem
import React, { Component } from 'react';
import './App.css';
import Axios from 'axios'
class App extends Component {
constructor(props) {
super(props);
this.state = {
error: null,
isLoaded: false,
items: []
};
}
componentDidMount() {
Axios({
method: "GET",
url: "https://reqres.in/api/users"
}).then(res => {
this.setState({
isLoaded: true,
items: res.data
})
console.log(res.data)
}).catch(err => {
console.log(err)
})
}
render() {
const { error, isLoaded, items = [] } = this.state;
if (error) {
return <div>Error: {error.message}</div>;
} else if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<div>
{items.map(function (item, i) {
return <div key={i}>
<p>{item.id}</p>
<img src={item.avatar} alt="Card" />
</div>
})}
</div>
);
}
}
}
export default App;
This is data from reqres
{"page":1,"per_page":3,"total":12,"total_pages":4,"data":
[ {"id":1,"first_name":"George","last_name":"Bluth","avatar":"https://s3.amazonaws.com/uifaces/faces/twitter/calebogden/128.jpg"},
{"id":2,"first_name":"Janet","last_name":"Weaver","avatar":"https://s3.amazonaws.com/uifaces/faces/twitter/josephstein/128.jpg"},
{"id":3,"first_name":"Emma","last_name":"Wong","avatar":"https://s3.amazonaws.com/uifaces/faces/twitter/olegpogodaev/128.jpg"}
]}
Here is error from react
Error from react
I just want to show my data :(
Looking at the API response the statement should be
items: res.data.data
looks like res.data is not something you can loop over it. try to check what's inside it
edit:
as you can see from you output:
{"page":1,"per_page":3,"total":12,"total_pages":4,"data":
[ {"id":1,"first_name":"George","last_name":"Bluth","avatar":"https://s3.amazonaws.com/uifaces/faces/twitter/calebogden/128.jpg"},
{"id":2,"first_name":"Janet","last_name":"Weaver","avatar":"https://s3.amazonaws.com/uifaces/faces/twitter/josephstein/128.jpg"},
{"id":3,"first_name":"Emma","last_name":"Wong","avatar":"https://s3.amazonaws.com/uifaces/faces/twitter/olegpogodaev/128.jpg"}
]}
your informations are inside the data property, so, just loop over it:
{items.data.map(function (item, i) {
return <div key={i}>
<p>{item.id}</p>
<img src={item.avatar} alt="Card" />
</div>
})}
I am trying to fetch the message outputted by the following endpoint:
http://helloworld-env-2.5fwknpgms8.us-east-2.elasticbeanstalk.com/
I just ran a create-react-app to create my application and changed the code in the App.js file
New Code:
import React, { Component } from 'react';
import './App.css';
class App extends React.Component {
constructor(props){
super(props);
this.state = {
error: null,
isLoaded: false,
items: ""
};
}
componentDidMount(){
console.log("mounting component");
fetch("http://helloworld-env-2.5fwknpgms8.us-east-2.elasticbeanstalk.com/")
.then((result) => {
this.setState({
isLoaded: true,
items: result
});
});
}
render() {
console.log("rendering");
const isLoaded = this.state.isLoaded;
if(isLoaded){
return (<div> {this.state.items} </div>);
}
else{
return (
<div>loading</div>
);
}
}
}
export default App;
I keep getting the loading message.
You need to parse the response from fetch:
componentDidMount(){
fetch("http://helloworld-env-2.5fwknpgms8.us-east-2.elasticbeanstalk.com/")
.then((result) => result.json()) // here
.then((result) => {
const { a } = result; // access 'a' key from response
this.setState({
isLoaded: true,
items: a
});
});
}
Here are the docs.
I'm learning React and practicing how to use 'fetch' in React.
I have successfully fetched some API. I listed some random content out of this API, such as 'Title', 'Author' and 'Points'. However, I noted that some don't have the 'Title'. I don't like those that don't have 'Title'(leaving it blank). I'd like to automatically add 'A/N' in those lists that don't have the 'Title'.
Does anybody can teach me how to do that?
Here is my code:
import React, { Component } from 'react';
import './App.css';
class App extends Component{
constructor(){
super();
this.state={
hits: [],
isLoading: false,
error: null,
}
}
componentDidMount(){
this.setState({
isLoading: true
})
fetch('https://hn.algolia.com/api/v1/search?query=')
.then(response => {
if(response.ok){
return response.json()
}else{
throw new Error('Something went wrong...')
}
})
.then(data => this.setState({
hits: data.hits,
isLoading: false
}))
.catch(error => this.setState({
error: null,
isLoading: false
}))
}
render(){
const {hits, isLoading, error} = this.state;
if(isLoading){
return <p>Loading ... </p>
}
if(error){
return <p>{error.message}</p>
}
return(
<div className="container">
{hits.map(data =>
<ul key={data.objectID}>
<li><a href={data.url}>Title: {data.title}</a></li>
<li>Author:{data.author}</li>
<li>Points: {data.points}</li>
</ul>
)}
</div>
)
}
}
export default App
You can make use of !! operator to achieve this
Here is you code
import React, { Component } from 'react';
import './App.css';
class App extends Component{
constructor(){
super();
this.state={
hits: [],
isLoading: false,
error: null,
}
}
componentDidMount(){
this.setState({
isLoading: true
})
fetch('https://hn.algolia.com/api/v1/search?query=')
.then(response => {
if(response.ok){
return response.json()
}else{
throw new Error('Something went wrong...')
}
})
.then(data => this.setState({
hits: data.hits,
isLoading: false
}))
.catch(error => this.setState({
error: null,
isLoading: false
}))
}
render(){
const {hits, isLoading, error} = this.state;
if(isLoading){
return <p>Loading ... </p>
}
if(error){
return <p>{error.message}</p>
}
return(
<div className="container">
{hits.map(data =>
<ul key={data.objectID}>
<li><a href={data.url}>Title: {!!data.title ? data.title : "A/N" }</a></li>
<li>Author:{data.author}</li>
<li>Points: {data.points}</li>
</ul>
)}
</div>
)
}
}
export default App
ALternative way to achieve this
Set const default_title to 'n/a'; and use in render function.
You can use map() and save data like this:
fetch('https://hn.algolia.com/api/v1/search?query=')
.then(response => {
if(response.ok){
return response.json()
}else{
throw new Error('Something went wrong...')
}
})
.then(data => this.setState({
hits: data.hits.map( item => {
if(!item.Title){
item.Title = 'A/N';
}
return item;
}),
isLoading: false
}))
.catch(error => this.setState({
error: null,
isLoading: false
}))