Fetch Array data from API ReactJS - arrays

i try fetch array data from a API with token, the problem is i fail to render/bind to display,every time debug will show error message like this. Please guide me, im new to react, this is my 1st app.
how to bind array to myadapater?
error
here my code:
import React, { Component } from "react";
import ReactDOM from "react-dom";
const url = " "; //api customer
const token = " "; //token
class Client extends Component {
constructor(props) {
super(props);
this.state = {
error: undefined,
isLoaded: false,
items: []
};
this.getData = this.getData.bind(this);
}
componentDidMount() {
this.getData();
}
getData() {
return fetch(url, {
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: "Bearer " + token
}
})
.then((res) => res.json())
.then(
(result) => {
this.setState({
isLoaded: true,
items: result
});
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
);
}
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>
<p>data {items}</p>
{items.map((items) => (
<div>{items.name}</div>
))}
</div>
);
}
}
}
export default Client;

There is only one real issue.
The use of {items} in the render method. If you want to display the actual JSON try {JSON.stringify(items)} instead.
Besides that i would also not use the same name in the map. So instead of items for the map function i would use item since you are dealing with one of the items.
<div>
<p>data {JSON.stringify(items)}</p>
{items.map((item) => (
<div>{item.name}</div>
))}
</div>
Additionally, since you only use getData in the componentDidMount you do not need to bind it in the constructor (that is required if you intent to pass that function to other component/functions outside of the current one)
And you also do not need to return anything for the getData function since you handle the result in the then handlers.
So,
class Client extends Component {
constructor(props) {
super(props);
this.state = {
error: undefined,
isLoaded: false,
items: []
};
}
componentDidMount() {
this.getData();
}
getData() {
fetch(url, {
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: "Bearer " + token
}
})
.then((res) => res.json())
.then(
(result) => {
this.setState({
isLoaded: true,
items: result
});
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
);
}
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>
<p>data {JSON.stringify(items)}</p>
{items.map((item) => (
<div>{item.name}</div>
))}
</div>
);
}
}
}

Related

API POST using fetch helper function doesn't render update after response is received

Beginner at React (and JS)...
I am trying to update text on the screen after my API helper function has completed a call. Instead, it returns empty. I have verified with the console that the data is being received. I followed the ComponentDidMount method from other similar questions but am still having no success. My code also seems to make multiple API calls, even though my intent is to only make one; I have to wonder if the issue stems from that.
Helper function:
export function apiHelper(url, data = {}, method = 'POST') {
return fetch(url, { // Return promise
method: method,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
})
.then(res => res.json())
.then((result) => {
console.log(result);
return result;
}, (error) => {
error = error;
})
}
React Component that renders incorrectly after data is received:
class Headache extends React.Component {
constructor(props) {
super(props);
this.state = {
apiResponse: null,
};
}
componentDidMount() {
apiHelper(URLredacted,JSONredacted)
.then(response => {
this.setState({
apiResponse: response
});
console.log("state set.",response)
});
}
render() {
const jsonResponse = JSON.stringify(this.props.apiResponse)
return (
<div>
<img className="logoheader" src = {logo}/>
<ColoredLine color="grey"/>
<p>{jsonResponse}</p>
</div>
);
}
}
export function apiHelper(url, data = {}, method = 'POST') {
return fetch(url, { // Return promise
method: method,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
})
.then(res => res.json())
.catch(err=>console.log(err))
}
second page:
class Headache extends React.Component {
constructor(props) {
super(props);
this.state = {
apiResponse: null,
};
}
componentDidMount() {
apiHelper(URLredacted,JSONredacted)
.then(response => {
this.setState({
apiResponse: response
});
console.log("state set.",response)
});
}
render() {
const jsonResponse = JSON.stringify(this.props.apiResponse)
return (
<div>
<img className="logoheader" src = {logo}/>
<ColoredLine color="grey"/>
<p>{jsonResponse && ""}</p>
</div>
);
}
}
if these code dont work you will be need asyn function because you need to wait to fetch data.

can't seem to get this array to work with splice

I am trying to get a new fortune to get included into my array when someone submits a fortune but I can't get it to work now matter what im trying. Do I like it to the other file where someones submit their fortune, or am I messing up somewhere else?
import React from "react";
import {Link} from "react-router-dom"
import AddFortune from "./add-fortune";
class Fortune extends React.Component {
constructor(props) {
super(props);
this.state = {
fortunes: [
"An exciting opporunity lies ahead",
"A long time friend will brirng wise advice in the coming week",
"You will find great fortunes in unexpected places",
"Never give up... Unless you want to thats cool too",
"111",
"222",
"333",
"444",
"Maybe a nap is what you need",
"Don't Text Your EX!"
],
array.push('
fortune: "" ');
array.splice(array.length, 0, '{fortune:""}');
array[array.length] = fortune: "";
}
}
componentDidMount() {
this.getFortune();
}
getFortune = () => {
let rand = Math.floor(Math.random() * (this.state.fortunes.length) + 0)
console.log(rand);
this.setState({
fortune: this.state.fortunes[rand]
})
}
render() {
return (
<body>
<div className="home-buttons-wrapper">
<button onClick={this.getFortune}>Your Fortune</button>
</div>
<h5>{this.state.fortune}</h5>
</body>
)
}
}
console.log('getFortune');
export default Fortune;
What im trying to get to be added to the fortunes file
import React, { Component } from 'react'
export default class AddFortune extends Component {
constructor(props) {
super(props)
this.state = {
nameInput: "",
loading: false,
error: false
}
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
}
handleChange(event) {
this.setState({ [event.target.name]: event.target.value })
}
handleSubmit(event) {
event.preventDefault()
this.setState({
loading: true,
error: false
})
fetch("https://backend-edwin.herokuapp.com/item/add", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
name: this.state.nameInput
})
})
.then(response => response.json())
.then(data => {
if (data.id) {
this.props.history.push("/fortune")
}
})
.catch(error => {
console.log("Error adding fortune ", error)
this.setState({
loading: false,
error: true
})
})
}
render() {
return (
<div className='add-item-wrapper'>
<h2>Add Fortune</h2>
<form onSubmit={this.handleSubmit}>
<input
type="text"
placeholder="fortune"
name="nameInput"
value={this.state.nameInput}
onChange={this.handleChange}
/>
<button type="submit" disabled={this.state.loading}>Add Fortune</button>
</form>
{this.state.loading ? <div className="loading">Submitting...</div> : null}
{this.state.error ? <div className="error">An error occured... Please try again later.</div> : null}
</div>
)
}
}
Here is a method to get a random fortune from a list of fortunes.
import React from "react";
class Fortune extends React.Component {
constructor(props) {
super(props);
this.state = {
fortunes: [],
fortune: '',
loading: true,
error: false
}
}
componentDidMount() {
fetch("https://backend-edwin.herokuapp.com/item/", {
method: "GET",
headers: { "content-type": "application/json" },
})
.then(response => response.json())
.then(data => {
this.setState({
loading: false,
fortunes: data, //check how the data is coming from api and add the variable here if fortunes list `if data.fortunes` then add data.fortunes here
error: false
}, this.getFortune)
})
.catch(error => {
console.log("Error fetching fortune ", error)
this.setState({
loading: false,
error: true
})
})
}
getFortune = () => {
let rand = Math.floor(Math.random() * (this.state.fortunes.length - 1) + 0)
console.log(rand);
this.setState({
fortune: this.state.fortunes[rand]
})
}
render() {
if(this.state.loading) {
return (<div>Loading .....</div>)
}
if(this.state.error) {
return (<div>Error occurred in API</div>)
}
return (
<div>
<div className="home-buttons-wrapper">
<button onClick={this.getFortune}>Your Fortune</button>
</div>
<h5>{this.state.fortune}</h5>
</div>
)
}
}
export default Fortune

Reactjs how to call magento 2 api with bearer (the server responded with a status of 401 (unauthorized))

I'm try to use reactjs (from localhost:80) to call (http://m2.example.com:80) magento 2 api, but it only return Error: the server responded with a status of 401 (unauthorized)"
import React from "react";
import ReactDOM from "react-dom";
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
error: null,
isLoaded: false,
items: []
};
}
componentDidMount() {
fetch("http://m2.example.com/rest/V1/products?searchCriteria[page_size]=20",{
method: 'GET',
mode: 'no-cors',
credentials: 'include',
withCredentials: true,
headers: {
'Authorization': 'Bearer 3nsi1y7pcun1atvhs87dxmokymquofii',
'Content-Type': 'application/json'
}
})
.then(res => res.json())
.then(
(result) => {
this.setState({
isLoaded: true,
items: result.items
});
},
// Note: it's important to handle errors here
// instead of a catch() block so that we don't swallow
// exceptions from actual bugs in components.
(error) => {
this.setState({
isLoaded: true,
error
});
}
)
}
render() {
const { error, isLoaded, items } = this.state;
if (error) {
return <div>Error: {error.message}</div>;
} else if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<ul>
{items.map(item => (
<li key={item.name}>
{item.name} {item.price}
</li>
))}
</ul>
);
}
}
}
/*const App = () => (
<div>
<h1>Hello world!!</h1>
</div>
)*/
ReactDOM.render(<MyComponent/>, document.getElementById("root"));
//ReactDOM.render(<App/>, document.getElementById("root1"));
Anyone know what's wrong with above code?
Try removing the mode: 'no-cors' and 'withCredentials: true' and handle CORS from the backend php magento2 - Please check this link on how to do it
fetch("http://m2.example.com/rest/V1/products?searchCriteria[page_size]=20",{
method: 'GET',
credentials: 'include',
headers: {
'Authorization': 'Bearer 3nsi1y7pcun1atvhs87dxmokymquofii',
'Content-Type': 'application/json'
}
After that it should work.

Method returning undefined even though fetch succeeds?

I have two components, Client and App, and a fetch function. App is the child component of Client. I want to update Client's state using the return value from the method App calls. However, Client's state response is undefined after the fetch. I'm not sure why this code does not work.
import React, { Component } from 'react';
import './App.css';
function post(user, token, data){
console.log('fetching...')
fetch(`/project`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Basic '+ btoa(user+':'+token),
},
body: JSON.stringify(data)
}).then(r => {
if (!r.ok)
throw Error(r.status);
r.json().then(r => {return(r)});
}).catch(error => {throw Error(error)})
}
class Client extends Component {
constructor(props) {
super(props);
this.state = {
user: '',
token: '111',
project: {'project':'demo'},
response: {},
};
this.updateState = this.updateState.bind(this);
};
updateState(){
const { user, token, project } = this.state;
post(user, token, project).then(text => this.setState({ response: text
}));
}
render() {
return (
<App updateState={this.updateState}/>
)
}
}
class App extends Component {
render() {
return (
<div className="App">
<button onClick={ () => {
this.props.updateState()} }>Fetch Project</button>
</div>
);
}
}
EDIT: I changed my post() to this and it works :)
async function post(user, token, data){
console.log('fetching...')
const response = await fetch(`/project`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Basic '+ btoa(user+':'+token),
},
body: JSON.stringify(data)
}).catch(error => {throw Error(error)});
if(!response.ok)
throw Error(response.status);
const obj = await response.json();
return(obj);
}
If you are working with promises, you can do something like this.
import React, { Component } from "react";
async function post() {
// fetch //
return await fetch("https://hipsum.co/api/?type=hipster-centric");
}
class Client extends Component {
constructor(props) {
super(props);
this.state = {
response: "12"
};
this.updateState = this.updateState.bind(this);
}
async updateState(res) {
const text = await res().then(res => res.text());
this.setState({ response: text });
}
render() {
return (
<>
{this.state.response}
<App updateState={this.updateState} />
</>
);
}
}
class App extends Component {
render() {
return (
<div>
<button
onClick={() => {
this.props.updateState(post);
}}
>
Fetch
</button>
</div>
);
}
}
export default Client;
sandbox
It will be nice to know all the code for the fetch function but I think the problem is mostly here:
this.props.updateState(post())
That call is synchronous and the fetching process isn't. You need a better approach with await or promises or a callback.

React API returns empty

fairly new to react but I have the following API data I want to create as a list or whatever:
https://jsonblob.com/53c7f296-d79d-11e8-839a-a312b719c60a
My react component looks like this:
class Contacts extends Component {
constructor(props) {
super(props)
this.state = {
contacts:[]
}
}
componentDidMount() {
fetch('https://api.billysbilling.com/v2/contacts?organizationId=kZeGqbBRSXyeeDoWNkF3jQ',{
headers: {
'X-Access-Token': API_KEY,
'Content-Type': 'application/json'
},
})
.then(response => {
return response.json();
})
.then(response => console.log(response))
.then(d => {
this.setState({ contacts: d });
console.log("state", this.state.contacts)
})
}
render() {
return (
<div>
{
this.state.contacts.map(((contact, index) =>
<th key={`${contact.contact}${index}`}>
<div>
<div>
{contact.contact}
</div>
</div>
</th>
))
}
</div>
);
}
But however it seems to return nothing.
The console.log actually shows the data, so I am pretty stuck.
It would be awesome if some of you could help.
The state also just returns an empty array in the react tools in chrome.
When you write then(response => console.log(response)), you are not returning anything, so d will be undefined in the function given to the following then.
You could write it like this instead:
fetch('https://api.billysbilling.com/v2/contacts?organizationId=kZeGqbBRSXyeeDoWNkF3jQ',{
headers: {
'X-Access-Token': API_KEY,
'Content-Type': 'application/json'
},
})
.then(response => {
return response.json();
})
.then(d => {
console.log(d);
this.setState({ contacts: d.contacts });
});

Resources