React — Requesting data using Fetch - api

I am trying to get some data from an API using Fetch without success. For some reason the request is failing and I am not able to render the data... as I am quite new to React and Fetch I am not sure where the error is. Is it something to do with the way I am requesting the API?
Thank you in advance
class App extends React.Component {
render() {
return <Data />
}
}
class Data extends React.Component {
constructor(props) {
super(props)
this.state = {
requestFailed: false,
}
}
componentDidMount() { // Executes after mouting
fetch('https://randomuser.me/api/')
.then(response => {
if (!request.ok) {
throw Error("Network request failed.")
}
return response
})
.then(d => d.json())
.then(d => {
this.setState({
data: d
})
}, () => {
this.setState({
requestFailed: true
})
})
}
render() {
if(this.state.requestFailed) return <p>Request failed.</p>
if(!this.state.data) return <p>Loading</p>
return (
<h1>{this.state.data.results[0].gender}</h1>
);
}
}
ReactDOM.render(<App />, document.getElementById('app'));
CodePen

As mentioned on the GITHUB docs, you can implement the fetch like
fetch('https://randomuser.me/api/')
.then((response) => {
return response.json()
}).then((d) => {
console.log('parsed json', d)
this.setState({
data: d
});
}).catch(function(ex) {
console.log('parsing failed', ex)
this.setState({
requestFailed: true
})
})
CODEPEN

fetch method should be
fetch('your_url')
.then (
response => {
if (response.status !== 200) {
return 'Error. Status Code: ' + response.status
}
response.json().then(result => console.log(result)) // do sth with data
}
)
.catch(function(err) {
console.log('Opps Error', err)
})

I think your problem is with
.then(response => {
if (!request.ok) {
throw Error("Network request failed.")
}
return response
})
There's no request object that has the property ok. Maybe you mean to check response.ok ?
.then(response => {
if (!response.ok) {
throw Error("Network request failed.")
}
return response
})

Related

use a function in action of auth modules in wizard module in vuex in vue

I have this function in auth.module.js:
async [VERIFY_AUTH](context) {
if (JwtService.getToken()) {
ApiService.setTokenAxios();
return (
ApiService.get("api/customer/me")
.then(({ data }) => {
console.log("auth request - useer:", data);
context.commit(SET_AUTH, data);
})
///////////
.catch(({ response }) => {
console.log(response);
context.commit(SET_ERROR, serviceErrors(response.data));
})
);
} else {
context.commit(PURGE_AUTH);
}
},
I want dispatch it in wizard.modules.js
[SPOUSES](context, data) {
console.log(data);
return new Promise(() => {
ApiService.post(`api/customer/${data.id}/spouses`, data.form).then(
({ data }) => {
console.log(data);
context.dispatch("auth/VERIFY_AUTH", null, { root: true });
}
);
});
},
I try it but it dont work
do you know what should I do?

Unable to set state from the response of the api

I have a following function in Api.js
const _getCategories = async () => {
var categories = [];
let token = await getJwt();
var config = {
method: 'get',
url: 'myurl',
headers: {
'Authorization': 'Bearer' + ' ' + token
},
data : ''
};
axios(config)
.then(function (response) {
if(response.status == 200)
{
let res = response.data;
// Create a variable having name in the list.
categories = res.data.apps.map(function(item) {
return {
title: item.name,
color: AppStyles.colorSet.analyticsColor,
lightColor: AppStyles.colorSet.analyticsLightColor,
icon: AppStyles.iconSet.analytics
};
});
// console.log('Returning Categories');
console.log(categories);
return categories;
//console.log(data1)
// Handle and fetch the list of apps
}
else
{
// API didn't go through, generate the error functions
}
})
.catch(function (error) {
console.log(error);
});
};
and I am loading it in homscreen.js
class DashboardScreen extends React.Component {
constructor(props) {
super(props);
const { navigation } = props;
navigation.setOptions({
title: 'Dashboard',
headerLeft: () => (
<TouchableOpacity
onPress={() => {
navigation.openDrawer();
}}
>
<Icon
style={AppStyles.styleSet.menuButton}
name="ios-menu"
size={AppStyles.iconSizeSet.normal}
color={AppStyles.colorSet.mainThemeForegroundColor}
/>
</TouchableOpacity>
),
});
this.state = {
categories: [],
};
}
componentDidMount() {
if (!this.state.data) {
Api.getCategories().then(data => console.log("The data is "+data))
.catch(err => { /*...handle the error...*/});
}
}
onPressCategory = item => {
// Handle onpress for the items
};
render() {
//console.log(this.state.categories);
categoryButtonsRow1 = this.state.categories.map((item, index) => {
if (index < 3) {
return (
<CategoryButton
onPress={() => this.onPressCategory(item)}
color={item.color}
lightColor={item.lightColor}
icon={item.icon}
title={item.title}
/>
);
}
});
return (
<ScrollView style={styles.container}>
<View style={styles.row}>{categoryButtonsRow1}</View>
</ScrollView>
);
}
}
But I am getting category as undefined while printing in render().
I even tried to create an async function in the homescreen.js and call the api with await and set the state after the same but still it is coming as undefined.
Any guesses to what I am doing wrong here. Can anyone help with the same. My best guess is that I am not handling the api request properly.
EDIT
I tried Use Async/Await with Axios in React.js but it is still printing undefined to the same.
The reason for getting undefined is the _getCategories is that its not returning anything and you are chaining using .then to get data so the caller has no way to get this data as a callback is not passed.
You can change the to await like this
const _getCategories = async () => {
var categories = [];
let token = await getJwt();
var config = {
method: 'get',
url: 'myurl',
headers: {
Authorization: 'Bearer' + ' ' + token,
},
data: '',
};
const response = await axios(config);
if (response.status == 200) {
let res = response.data;
// Create a variable having name in the list.
categories = res.data.apps.map(function (item) {
return {
title: item.name,
color: AppStyles.colorSet.analyticsColor,
lightColor: AppStyles.colorSet.analyticsLightColor,
icon: AppStyles.iconSet.analytics,
};
});
// console.log('Returning Categories');
console.log(categories);
return categories;
//console.log(data1)
// Handle and fetch the list of apps
} else {
// API didn't go through, generate the error functions
return null;
}
};
And you can set the state in componentDidMount (should be async)
this.setState({categories:await api._getCategories()});

React native _this.state.data.map is not a function

In console, I can get this.state.data in render. Everything looks normal. But I get this.state.data.map is not a function error. What am I doing wrong?
I would be very happy if there is someone who can help. Thanks in advance
export default class ProfileScreen extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
hash: '',
};
}
_retrieveData = async () => {
try {
const value = await AsyncStorage.getItem('token');
console.log(value);
this.setState({
hash: value,
});
} catch (error) {
// Error retrieving data
}
};
getInfo = async () => {
try {
const response = await axios.get('http://yakakartim.net/museb/kollektif/loginInfo?hash=' + this.state.hash);
this.setState({
data: response.data.message
})
} catch (e) {
console.log(e)
}
};
componentDidMount() {
this._retrieveData();
this.getInfo()
}
list = () => {
return this.state.data.map(info => {
return (
<View style={{ margin: 10 }}>
<Text>{info.email}</Text>
</View>
);
});
};
render() {
console.log('render',this.state.data)
console.log('render',this.state.hash)
return <View>{this.list()}</View>;
}
}
This is because you are updating the data variable which is initially an array in state but later in getInfo function you have update it like this
this.setState({
data: response.data.message
})
I dont know what is in "message". But if it is not an array, then map function will not work with "data" as it only works with variables which are iterate-able. I mean which are of array data type.
thanks, the incoming data is not an array. I found the solution like this.
this.setState({
data: [response.data.message]
})

map is not a function in react-native

I want to get some data from api and display data in my app. This is my code,
class AlbumList extends Component {
state = { albums: [] };
async componentWillMount() {
try {
const data = await axios.get(
'https://rallycoding.herokuapp.com/api/music_albums'
);
this.setState({ albums: data });
} catch (err) {
console.error(err.message);
}
}
renderAlbums() {
return this.state.albums.map(album => <Text>{album.title}</Text>);
}
render() {
return (
<View>
{this.renderAlbums()}
</View>
);
}
}
this will give a error this.state.albums.map is not a function..
any way to solve this?
The error "map it not a function" occurs because axios don't return an array.
Axios returns an object with keys like status, data.
const data = await axios.get(
'https://rallycoding.herokuapp.com/api/music_albums'
);
console.log(data);
console.log(data.data); // album data
this.setState({album: data.data});
When using without await:
axios.get('https://rallycoding.herokuapp.com/api/music_albums')
.then(response => {
this.setState({ album: response.data });
})
.catch(error => {
console.log(error);
});
So you must check the object key "data" returned by axios get.

Showing alert from service class in react-native

I have an HTTP service class which is responsible for communication with my Laravel based API. I want the HTTP service class to trigger React Native Alert box when there is a 401 authentication issue. Or 403 Access denied issue or 422 which is validation issue.
I have the basic HTTP service class ready, but I am not able to show an alert from my HTTP service because it is not a react component and I want to know if I can use such a global service class and still trigger Native components.
Below is my code:
import axios from 'axios';
import {
AsyncStorage,
Alert
} from 'react-native';
class HttpService {
async get(url) {
let at = await AsyncStorage.getItem('access_token', (error, accessToken) => {
return accessToken;
});
let data = await axios.get(url, {headers: { 'Authorization': 'Bearer ' + at }})
.then(response => {
console.log('response', response);
return response;
})
.catch(error => {
let message, title = '';
if (!error.response) {
message = error;
}
if (error.response.status === 401) {
message = error.response.data.message;
title = 'Authentication issue'
}
Alert.alert(title, message, [
{ text: 'Ok', onPress: () => console.log(123) }
]);
});
return data;
}
post() {}
}
export default HttpService;
Why not just return the errors too? So you can determine what occurred so the component that makes the HttpService call knows when to show the Alert.
class yourComponent extends Component{
constructor() {
this.state = {
token: null,
isLoaded: false,
error: null
}
}
componentDidMount() {
HttpService.get('someUrl')
.then(res => {
this.setState({
token: res,
isLoaded: true
});
}, (error) => {
this.setState({
error: error,
isLoaded: true
});
})
}
}
render() {
const { error, isLoaded, items } = this.state;
if (error) {
// return your Alert here
} else if (!isLoaded) {
// return loading component;
} else {
// return your main component
}
}
}