map is not a function in react-native - 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.

Related

ReactNative: AsyncStorage Problem : I can't retrieve Data the correctly

I am trying to use the AsyncStorage in my Project by Saving the token to the AsyncStorage by using setItem()
Action that response with token
import axios from 'axios';
import {URL, Config} from '../../service/Api';
import AsyncStorage from '#react-native-async-storage/async-storage';
export const checkSmsToLoginUser = value => async dispatch => {
dispatch({type: 'USER_LOGIN_REQUEST'});
try {
const {data} = await axios.post(`${URL}user/checkSMSCode`, value, Config);
console.log(data.token); // it consoles the token
await AsyncStorage.setItem('USER_TOKEN', data.token);
dispatch({type: 'USER_LOGIN_SUCCESS', payload: data?.token});
} catch (error) {
dispatch({type: 'USER_LOGIN_ERROR', payload: error});
}
};
and I dispatch the action in the component, then I try to get the the token from the the AsyncStorage by using getItem
const getData = async () => {
try {
const token = await AsyncStorage.getItem('USER_TOKEN');
return token, JSON.parse(token);
} catch (error) {
return error;
}
};
console.log(getData(), 'token From AsyncStorage');
but when I console the token that comes from the AsyncStorage, I have some sort of unhandled promise
any clue what's the problem or maybe solution?
This might help
function App() {
const getData = async () => {
try {
const token = await AsyncStorage.getItem('USER_TOKEN');
// Log here
console.log(JSON.parse(token), 'token From AsyncStorage');
} catch (error) {
return error;
}
};
useEffect(() => {
getData(); // call here
}, []);
return (
<View>
...
</View>
);
}
You are printing an async function without awaiting for it.
The code is correct, but the console log is not correct:
console.log(getData(), 'token From AsyncStorage'); // missing async logic
Insert the console log inside the getData function, or await for the response.
By Adding the getData() in UseEffect and handling the promise by using then().catch() worked for me
useEffect(() => {
getData()
.then(res => {
console.log(res, 'it worked');
setToken(res);
})
.catch(err => {
setError(err);
console.log(err);
});
}, []);

Can't save parsed API data to state in React Native

Using React-Native I'm trying to pull from an API, convert the provided XML to JS using react-native-xml2js and save it to state.
I have the converted output pushed to console successfully but when I try to save to state and have that state outputted on screen I'm getting a reference error stating that result is not defined.
import React, { Component } from 'react'
import { View, Text } from 'react-native'
import { parseString } from 'react-native-xml2js'
class MPList extends Component {
state = {
data: '',
}
componentDidMount = () => {
fetch('http://data.parliament.uk/membersdataplatform/services/mnis/members/query/House=Commons%7CIsEligible=true', {
method: 'GET'
})
.then((response) => response.text())
.then((responseText) => {
parseString(responseText, function (err, result) {
console.log(result);
return result;
})
this.setState({
data : result
})
})
.catch((error) => {
console.log('Error fetching the feed: ', error);
});
}
render() {
return (
<View>
<Text>
{this.state.data}
</Text>
</View>
)
}
}
export default MPList
New to this, any help very much appreciated!
Try setting the state from within the parseString callback function. I've used an arrow function so you don't need to add explicit bindings.
parseString(responseText, (err, result) => {
if(result) {
this.setState({ data: result });
}
});
Your current code:
parseString(responseText, function(err, result) {
// result is defined here
});
// result is undefined here
this.setState({ data: result });

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]
})

Integrating Pull-To-Refresh in a ScrollView with Redux in React Native

I am trying to add pull-to-refresh functionality to a <ScrollView> using a refreshControl and integrate it with Redux.
Example from https://facebook.github.io/react-native/docs/refreshcontrol:
_onRefresh = () => {
this.setState({refreshing: true});
fetchData().then(() => {
this.setState({refreshing: false});
});
}
My problem is that my own fetchData function dispatches an action for the reducer to handle, so as far as I understand it, it is not a thenable promise. So I don't fully understand the integration with Redux in this case. What do I need to change in my code to be able to set refreshing to false as in the above example?
PostFeedScreen.js
// on mount, fetch all posts from the API
componentDidMount() {
this.props.fetchPostsFromAPI();
}
_onRefresh = () => {
this.setState( { refreshing: true } );
this.props.fetchPostsFromAPI().then( () => { // error
this.setState( { refreshing: false } );
});
}
// map dispatch to props
const mapDispatchToProps = ( dispatch ) => {
return {
fetchPostsFromAPI: () => {
dispatch( fetchPostsFromAPI() );
}
}
}
PostActions.js
// fetch all posts
export function fetchPostsFromAPI() {
return( dispatch ) => {
let loadData = new Promise( ( resolve, reject ) => {
resolve( postsInitial ); // using dummy data for now
})
loadData
.then( posts => dispatch( fetchPostsSuccess( posts ) ) );
}
// is used if posts were succesfully loaded
function fetchPostsSuccess( posts ) {
return {
type: PostConstants.FETCH_POSTS_SUCCESS,
data: posts,
}
}
PostReducer.js
const PostReducer = ( state = initialState, action ) => {
switch( action.type ) {
// if fetching data was successful
case PostConstants.FETCH_POSTS_SUCCESS: {
return {
...state,
posts: action.data,
}
}
default: {
return state
}
}
You get an error cause you call .then on something who don't return a promises. Just add return in front of your loadData, cause you can chain promises.
export function fetchPostsFromAPI() {
return dispatch => {
let loadData = new Promise((resolve, reject) => {
resolve(postsInitial);
});
return loadData.then(posts => dispatch(fetchPostsSuccess(posts)))
};
}

React — Requesting data using Fetch

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
})