Get answers from API request as array - reactjs

I'm trying to make an API request and display them, I think that I have to render them as array but have problems with this. Here is my code
class RecipesList extends React.Component {
constructor(props) {
super(props);
this.state = {
searchResult: ''
};
}
componentDidMount() {
fetch('https://api.edamam.com/search?q=chicken&app_id=ec279fce&app_key=51017bcd32e69bcb0cc8b5f99e8783ca')
.then(resp => resp.json())
.then(resp => this.setState({searchResult: resp})
);
}
render() {
return <div>{this.state.searchResult}</div> //???
}
}
class App extends React.Component {
render() {
return <RecipesList/>;
}
}
ReactDOM.render(
<App/>, document.querySelector('#app'));

If you just want to see your data, just do:
componentDidMount() {
fetch('https://api.edamam.com/search?q=chicken&app_id=ec279fce&app_key=51017bcd32e69bcb0cc8b5f99e8783ca')
.then(resp => resp.json())
.then(resp => this.setState({searchResult: JSON.stringify(resp)})
);
}
You can also log your response object like:
componentDidMount() {
fetch('https://api.edamam.com/search?q=chicken&app_id=ec279fce&app_key=51017bcd32e69bcb0cc8b5f99e8783ca')
.then(resp => resp.json())
.then((resp) => {
console.log(resp);
this.setState({searchResult: JSON.stringify(resp)})
});
}
The problem was: (I saw this error in the log)
Uncaught (in promise) Error: Objects are not valid as a React child
(found: object with keys {q, from, to, params, more, count, hits}). If
you meant to render a collection of children, use an array instead or
wrap the object using createFragment(object) from the React add-ons.
Check the render method of [MyComponent]...
So in fact, the resp in the 2nd callback is an object, which cannot be rendered, so you can either convert it to string to see if your API works, or loop through the object to render it properly based on your need!
Feel free to post here some new errors in your console, so we can find a good way to render your data, thanks

Related

Accessing JSON Array Data in React.js/Next.js Combo

Given an API which returns JSON data like:
["posts":
{"id":1,
"name":"example",
"date":"exampledate",
"content":"examplecontent",
"author":"exampleauthor"},
{"id":2,
..]
The length of the array is unknown.
I am fetching data via isomorphic-fetch like this:
displayPosts.getInitialProps = async function() {
const res = await fetch('.../post');
const data = await res.json();
return{
posts: data.posts
}
}
which is working (console.log.stringify(data)).
Now i want to display such posts on my displayPosts page.
Therefore i am using the following React Component.
class Posts extends React.Component {
stat = {
// here i don't know how to set the state
}
render() {
return (
// i want to render the data here
);
}
}
export default Posts;
Question: How do i set a state, so that i can neatly display every post in my displayPosts.js page with
<Posts posts={props.Posts}/>
?
class Posts extends React.Component {
state = {
posts: []
}
componentDidMount() {
this.savePosts();
}
componentDidUpdate() {
this.savePosts();
}
savePosts = () => {
if(this.props.posts){
//do any other processing here first if you like
this.setState({
posts: this.props.posts
});
}
}
You probably don't need to save the posts in state, since you could just pull them from props directly. But if you need to process or transform them somehow, it might make sense.
In either case, you just hook into the lifecycle methods to do this.
Note: This will set the state every time the component updates. Often you only want to update the state when that specific prop changes. If so, you can first compare the old and new props to see if it has changed in a way that means you want to update your state.

Return Fetched Data from Axios in React

Have a question about rendering fetched data with Axios. I’m able to log returned data to the console, however, it will not render on the screen.
I’m using an NPM Bitly module: https://www.npmjs.com/package/bitly
const BitlyClient = require('bitly');
const bitly = BitlyClient('ACCESS TOKEN');
State
class Example extends Component {
constructor() {
super();
this.state = {
landing: 'https://www.google.com/',
newUrl: 'https://www.udacity.com/'
};
API Call
componentDidMount() {
bitly.shorten(this.state.landing)
.then((response) => {
this.setState({newUrl: response.data.url })
console.log(response.data.url);
})
.catch(function(error) {
console.error(error);
});
}
This returns data to the console but does not render to the page.
Render to Page
<Component> {this.newUrl} </>
What am I missing?
It should be {this.state.newUrl}.
Literally started to work as soon as I posted this smh.
I just updated the component to include the state.
Did not work
<Component> {this.newUrl} </>
Does Work
<Component> {this.state.newUrl} </>

React component is rendering but not updating when state is updating

React component is showing data when state is null but, when its getting data then its not updating the content of the view.
constructor(props){
super(props);
this.state = {
post: null
}
this.getTotalDownloadSize = this.getTotalDownloadSize.bind(this);
}
componentWillMount(){
const {match} = this.props;
const postId = _.get(match, 'params.id');
getDownloadInfo(postId).then((response) => {
this.setState({
post: _.get(response, 'data')
});
}).catch((err) => {
console.log("an error while fetching data", err);
})
}
inside my render i am getting null value for render(){
render(){
const {post} = this.state;
console.log{post};
const files = _.get(post, 'files', []);
)
initially its showing the null value but after it has value but its not updating the content of the view.
can anyone help me with this.
thanks in advance.
componentDidMount is place where you can place request logic.
componentDidMount() {
const {match} = this.props;
const postId = _.get(match, 'params.id');
getDownloadInfo(postId).then((response) => {
this.setState((state) => ({ post: _.get(response, 'data')}));
}).catch((err) => {
console.log("an error while fetching data", err);
})
}
If your data came from an asynchronous request you should use componentDidMount
Invoked once, only on the client (not on the server), immediately
after the initial rendering occurs. At this point in the lifecycle,
you can access any refs to your children (e.g., to access the
underlying DOM representation). The componentDidMount() method of
child components is invoked before that of parent components.
If you want to integrate with other JavaScript frameworks, set timers
using setTimeout or setInterval, or send AJAX requests, perform those
operations in this method.

React: How ensure completion of some Life-cycle methods before others

I'm using React Native 0.43. I've one component, named ApiComponent. In componentWillMount method of this component, I'm fetching some results from an API and I want this result in my render method. I'm using following code (abridged version) in my component:
export default class ApiComponent extends Component {
constructor(props) {
super(props);
this.state = {
statement: {},
};
}
componentWillMount() {
fetch('http://example.com/api_url/')
.then(response => response.json())
.then(data => this.setState({ statement: data }))
.catch(error => console.error(error));
}
render() {
return (
<Text>{'Rendering API: ' + console.log(this.state.statement)}</Text>
);
}
}
Now, when I run this code I get an empty result in my console Rendering API: {}. As per my understanding, the render method executes before the results are returned from the API and therefore the state is not being updated with the results.
My question is, how I can make sure that my render method only executes when the code in my componentWillMount completes its execution?
You can use a ternary operation to ensure the text only renders if this.state.statement is true
return (
{ this.state.statement ? <Text>{'Rendering API: ' + console.log(this.state.statement)}</Text> : null }
)

Accessing a promise with the componentDidMount

I'm accessing a promise that gets returned from my mock API. The React component looks like what you see below
import React from 'react';
import StudentListStatistics from './StudentListStatistics';
import StudentStatisticsApi from '../../api/mockStudentApi';
class AboutPage extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
studentsStatistics: []
};
}
componentDidMount() {
StudentStatisticsApi.getAllStudentsStatistics().then(
studentsStatistics => {
this.setState({
studentsStatistics: studentsStatistics
});
debugger;
}
);
console.log(this.state.studentsStatistics);
}
render() {
return (
<div>
<h2>Student Body Statistics</h2>
<StudentListStatistics studentsStatistics={this.state.studentsStatistics}/>
</div>
);
}
the mock API looks like this
class StudentApi {
static getAllStudentsStatistics() {
return new Promise((resolve, reject)=> {
setTimeout(()=> {
resolve(Object.assign([], studentsStatistics));
}, 1000);
});
}
I'm not sure why the this.state.studentsStatistics is always an empty array. If I step through the code then studentsStatistics array is being returned correctly from my mock API within the then callback.
Can someone point out what I might be missing.
The issue is two-fold:
getAllStudentsStatistics() is asynchronous, which means that it will eventually yield a result, but not immediately;
setState() is also "asynchronous", in that it won't change this.state immediately after it got called.
To work around that, and log the mocked data, you need to first wait for the promise to resolve, and then to also wait for setState to acknowledge that the state has changed (by passing it a callback function):
componentDidMount() {
let promise = StudentStatisticsApi.getAllStudentsStatistics();
promise.then(studentsStatistics => {
this.setState({
studentsStatistics: studentsStatistics
}, () => {
console.log(this.state.studentsStatistics);
}
});
}
I think this also means that your StudentListStatistics component will initially be rendered with an empty array as input. Only once the promise has been resolved will it receive the mocked data.

Resources