Await is only allowed within async functions error react native - react-native

I am new to react native and trying to save user obejct in application storage using await AsyncStorage.setItem('user', res[1].data); However I am getting error as
handleLogin = async() => {
NetInfo.fetch().then(state => {
if (state.isConnected) {
const {navigate} = this.props.navigation;
const data = {
email: this.state.userName,
password: this.state.password
};
fetch(`${DOMAIN_URL}/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data)
})
.then((response) => {
const statusCode = response.status.toString();
const data = response.json();
return Promise.all([statusCode, data]);
})
.then((res) => {
if (res[0] == 200) {
await AsyncStorage.setItem('user', res[1].data);
navigate('Home');
}else{
Alert.alert(
res[1].message
);
}
})
.catch((error) => {
console.error(error);
});
}
else {
Alert.alert(
"No Internet!",
"Needs to connect to the internet in order to work. Please connect tablet to wifi and try again.",
[
{
text: "OK",
onPress: () => { }
}
]
);
};
})
};
I have made the handleLogin async but it doesn't solve the error. What is the correct way to store user obejct?

It is recommended that you use react-native-easy-app , through which you can access any data in AsyncStorage synchronously.
Sample_Hooks
StorageController

navigateToHome = async (user) => {
const { navigate } = this.props.navigation;
await AsyncStorage.setItem('user', user);
navigate('Home');
}
handleLogin = async() => {
NetInfo.fetch().then(state => {
if (state.isConnected) {
const data = {
email: this.state.userName,
password: this.state.password
};
fetch(`${DOMAIN_URL}/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data)
})
.then((response) => {
const statusCode = response.status.toString();
const data = response.json();
return Promise.all([statusCode, data]);
})
.then((res) => {
if (res[0] == 200) {
navigateToHome(res[1].data);
}else{
Alert.alert(
res[1].message
);
}
})
.catch((error) => {
console.error(error);
});
}
else {
Alert.alert(
"No Internet!",
"Needs to connect to the internet in order to work. Please connect tablet to wifi and try again.",
[
{
text: "OK",
onPress: () => { }
}
]
);
};
})
};

Related

how to fetch data from Api folder in next.js

I"m facing this problem, I store my submitted data in api folder from a page and i successfully can store it and when i console.log it I can see the data but the problem is when I try fetch it to a page where I want show all this data then I didn't get any result, it's shows empty object:
this is the page from where I submitted data to api folder/page
const handleSubmitAllData = async (e) => {
e.preventDefault();
const allData = {
addStory,
selectedVideoUrl,
};
console.log("AllNftData:", allData);
try {
const { data } = await axios({
url: "/api/uploadNftData",
method: "POST",
data: allData,
});
console.log("response Data", data);
} catch (error) {
console.log("Error", error);
}
router.push("/template/marketplace");
};
this is the api page where store data, when console.log the data i see it that's means it's working
this is code of api page
const { log } = console;
export default function teamAdd(req, res) {
if (req.method === "POST") {
const nftData = req.body;
log("Req payload", nftData);
res.json(nftData);
}
return res.status(500).json({
msg: "this needs to be post request",
});
}
and this is page where I try to fetch this store data from api. this is code , it's not working. I try so many time but it's always comes out with not data
function page() {
const [data, setData] = useState(null);
const [isLoading, setLoading] = useState(false);
const [comments, setComments] = useState([]);
const fetchComments = async () => {
const response = await fetch("/api/uploadNftData");
const data = await response.json();
setComments(data);
console.log(data);
};
useEffect(() => {
setLoading(true);
fetch("/api/uploadNftData", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({}),
})
.then((res) => {
console.log(res);
return res.json();
})
.then((data) => {
console.log(data);
setData(data);
setLoading(false);
})
.catch((error) => {});
}, []);
if (isLoading) return <p>Loading...</p>;
if (!data) return <p>No profile data</p>;
return (
<>
<Main>
<Templatepage>
<TemplateHeader />
<Herosec>
marketplace
<Box
sx={{
background: "#000",
height: "200px",
width: "200px",
margin: "80px",
}}
>
<h1 style={{ color: "#fff" }}>{data.addStory}</h1>
<p style={{ color: "#fff" }}>{data.selectedVideoUrl}</p>
</Box>
</Herosec>
</Templatepage>
</Main>
</>
);
}
What happens if you try to update the dependency array of the useEffect with data
useEffect(() => {
setLoading(true);
fetch("/api/uploadNftData", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({}),
})
.then((res) => {
console.log(res);
return res.json();
})
.then((data) => {
console.log(data);
setData(data);
setLoading(false);
})
.catch((error) => {});
}, [data]);
And I would change the default state of
const [data, setData] = useState(null);
to something more reliable like some custom interface or type.
You can try to verify if data is null in useEffect and then do the request.
It should look something like this:
useEffect(() => {
if(data === null){
setLoading(true);
fetch("/api/uploadNftData", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({}),
})
.then((res) => {
console.log(res);
return res.json();
})
.then((data) => {
console.log(data);
setData(data);
setLoading(false);
})
.catch((error) => {});
}
}, [data]);

How to upload a file in react-native iOS?

While trying to upload a file I ran into an issue on iOS, the code works fine on android. After a bit of googling, I found that it is a known issue in react-native iOS and has a bug report submitted. This is the issue. I want to know if there is any other way to upload files on iOS. Below is the snippet of code I'm using. Please let me know if there is something that can be done.
const resp = await fetch(uploadUrl, {
method: 'POST',
headers: {
'content-type': 'multipart/form-data',
},
body: file, // file is File type
});
You can something like below code snippet
function uploadProfileImage(image, token) {
const url = ServiceUrls.UPLOAD_PROFILE_IMAGE
return uploadResourceWithPost({
url,
authToken: token,
formData: createFormData(image),
})
}
const createFormData = (data) => {
const form = new FormData()
form.append('file', {
uri: Platform.OS === 'android' ? data.uri : data.uri.replace('file://', ''),
type: 'image/jpeg',
name: 'image.jpg',
})
return form
}
const uploadResourceWithPost = ({ url, authToken, formData }) => {
return handleResponse(axios.post(url, formData, defaultUploadOptions(authToken)))
}
const defaultUploadOptions = (authToken) => ({
timeout,
headers: {
'X-Auth-Token': authToken,
'Content-Type': 'multipart/form-data',
},
})
const handleResponse = (responsePromise) => {
return NetInfo.fetch().then((state) => {
if (state.isConnected) {
return responsePromise
.then((response) => {
return ResponseService.parseSuccess(response)
})
.catch((error) => {
return ResponseService.parseError(error)
})
}
return {
ok: false,
message: 'Check your network connection and try again.',
status: 408,
}
})
}
const parseSuccess = ({ data, headers }) => ({ ...data, headers, ok: true })
const parseError = ({ response }) => {
let message = 'Check your network connection and try again.'
let status = 408
if (response && response.data) {
const { data } = response
message = data.message
status = data.code
}
return { status, message }
}

Getting JSON info from API

I'm using Axios(Apisauce) to connect API to React Native App;
this is the JSON file I'm trying to show in-app using FlatList :
{
"data": {
"sideMenu": {
"url": "https://google.com",
"icons": [
{
"id": 1,
"url": "https://google.com",
"status": 1
},
]
},
}
}
when I try to log it into the console, using console.log(response.data) returns all API info, but using console.log(response.data.data) doesn't return the object I'm looking for!
I've tried JSON.stringify() or toString() but none of them seem to Work.
my Axios Code :
const getServices = () => {
const service = "https://api.team-grp.ir/app/json/services2.json/";
return client.get(service);
};
My Source Code:
const ServiceInfo = async () => {
await getServices()
.then((response) => {
if (response.ok) {
setServicesData(response.data.data);
}
})
.catch((error) => {
console.warn(error);
setServicesData([]);
});
};
useEffect(() => {
ServiceInfo();
});
you should not use async/await with .then/.cache ...
this code is working for me:
(you can also see my sample code image at the bottom of this answer with a fake getService function, and you will see that logged response is correct)
const ServiceInfo = () => {
getServices().then((response) => {
if (response.ok) {
setServicesData(response.data.data);
}
})
.catch((error) => {
console.warn(error);
setServicesData([]);
});
};
useEffect(() => {
ServiceInfo();
}, []);
const ServiceInfo = async () => {
await getServices()
.then((response) => {
return response.json();
})
.then((response) => {
setServicesData(response.data);
})
.catch((error) => {
console.warn(error);
setServicesData([]);
});
};
Try this

React-native login with API refresh HomeScreen after login with another user

After I log out with a user and then log in with another, the data of the last user persists in the main screen, I need for that Main screen to refresh after another user logs-in.
How is it possible to do that?
this is in my componentDidMount()
async componentDidMount() {
await Font.loadAsync({
'AbhayaLibre-Regular': require('../assets/fonts/AbhayaLibre-Regular.ttf'),
'AbhayaLibre-Bold': require('../assets/fonts/AbhayaLibre-Bold.ttf'),
});
this.setState({ fontLoaded: true });
this.authCheck()
if (this.state.loggedIn == "false") {
this.props.navigation.navigate("Login");
} else {
this.authUser();
this.fetchSubjects();
}
}
It puzzles me because I'm not sure how to run that code again AFTER a new user logs-in after another logged out.
Code snipped of the login:
<Button icon="send" mode="contained" text="#1ebc61" color="white" onPress={() => {
axios.post('http://homewrk.test/api/auth/login', {
email: this.state.email,
password: this.state.password
}).then(res => {
this.setState({ token: res.data.access_token });
this.storeKey();
this.props.navigation.navigate("Home");
}).catch(() => {
this.setState({ error: true })
})
}}>
authCheck()
async authCheck() {
const token = await AsyncStorage.getItem('access');
const access = 'Bearer ' + token;
console.log(access);
axios.get(`http://homewrk.test/api/check`, {
headers: {
'Authorization': access,
}
}).then(res => {
const isLoggedIn = res.data;
this.setState({ loggedIn: isLoggedIn });
})
}
storing the key:
storeKey = async () => {
try {
await AsyncStorage.setItem('access', this.state.token);
console.log("done");
} catch (e) {
console.log(e);
}
}
async componentDidMount() {
await Font.loadAsync({
'AbhayaLibre-Regular': require('../assets/fonts/AbhayaLibre-Regular.ttf'),
'AbhayaLibre-Bold': require('../assets/fonts/AbhayaLibre-Bold.ttf'),
});
this.focusListener = this.props.navigation.addListener("willFocus", () => {
this.authCheck()
if (this.state.loggedIn == "false") {
this.props.navigation.navigate("Login");
} else {
this.authUser();
this.fetchSubjects();
}
});
}
componentWillUnmount() {
this.focusListener.remove();
}

React Native: setState doesn't work when calling try-catch function

I tried to call APP with this code imported from another file and it worked fine:
import FormData from 'FormData';
import AsyncStorage from '#react-native-community/async-storage';
let formData = new FormData();
formData.append('userId', '1'); // < this is what I want to change
formData.append('key', '***'); //my key
export function getScoreFromAPI () {
return fetch('https://www.globalfidelio.com/gfn_arcol/api/transaction.php',{
method : 'POST',
headers : {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data'
},
body : formData
} )
.then((response) => {
return response.json()
})
.catch((error) => console.log("l'erreure est: " + error))
}
but now I want to change my userId from 1 to an constante from Asyncstorage, so I decide to change my code to this:
constructor(props) {
super(props)
this.state = { infos: [], userId: '' }
}
componentWillMount() {
this.getScoreFromAPI().then(data => {
this.setState({ infos: data })
});
console.log(this.state.infos);
AsyncStorage.getItem(USERID_STORED)
.then((data) => {
if (data) {
this.setState({userId:data})
}
});
}
async getScoreFromAPI() {
let formData = new FormData();
formData.append('userId', this.state.userId);
formData.append('key', '***'); //my key
try {
let response = await fetch('https://www.globalfidelio.com/gfn_arcol/api/transaction.php',{
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data'
},
body: formData
})
let res = await response.json();
} catch(error) {
console.warn("errors are " + error);
}
};
with a try-catch function but when I call getScoreFromAPI() in ComponentWillMount() I can't setState with received data, I still have an empty array in info:[]
my questions:
how can I replace '1' in userId by a value in asyncstorage in the first file ?
if it isn't possible, what I have do to setState info: [] with my data reveived
I've simplified your code into a promise chain in which calling getScoreFromAPI will execute after getting the userId from AsyncStorage, then storing the response into the infos state, while returning null if there was an error, and logging the error to the console. The data was not previously returned from getScoreFromAPI, so the value would always become null. I have not tested this code, but this should give you a good base to work from:
import FormData from 'FormData';
import AsyncStorage from '#react-native-community/async-storage';
export default class Test {
constructor() {
this.state = {
infos: null,
userId: ''
};
}
componentDidMount() {
AsyncStorage.getItem(this.state.userId)
.then(userID => {
this.setState({ userId: userID || '' });
})
.then(() => {
return this.getScoreFromAPI();
})
.then(data => {
this.setState({ infos: data });
})
.catch(console.error);
}
getScoreFromAPI = () => {
const formData = new FormData();
formData.append('userId', this.state.userId);
formData.append('key', '***'); //my key
fetch('https://www.globalfidelio.com/gfn_arcol/api/transaction.php', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data'
},
body: formData
})
.then(response => {
// use response data here
return response.json();
})
.catch(e => {
console.error(e);
return null;
});
};
}
You're doing your API call before fetching your value from AsyncStorage (I know this is async but it's not very readable if you do it that way).
getScoreFromAPI doesn't return anything, that's why your setState isn't working.
You don't need to use try and catch here, promises have their own error handling mechanism (the .catch() method).
I think callbacks are more readable and lead to less bugs than using .then() in code.
This is how I would do it:
constructor(props)
{
super(props);
this.state = { infos: [], userId: '' };
this.onSuccess = this.onSuccess.bind(this);
this.onFailure = this.onFailure.bind(this);
}
componentWillMount()
{
// Get userID from local storage, then call your API
AsyncStorage.getItem(YOUR_KEY)
.then(userID=> {
if (userID)
{
this.setState({ userId : userID }, () => {
this.getScoreFromAPI(this.onSuccess, this.onFailure);
});
}
});
}
onSuccess(data)
{
this.setState({
infos : data
});
}
onFailure(err)
{
console.warn('Error ' + err);
}
getScoreFromAPI(onSuccess, onFailure)
{
let formData = new FormData();
formData.append('userId', this.state.userId);
formData.append('key', '***'); //your key
fetch('https://www.globalfidelio.com/gfn_arcol/api/transaction.php', {
method : 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data'
},
body: formData
})
.then(res => res.json())
.then(json => {
onSuccess(json);
})
.catch(err => {
onFailure(err);
});
}
It's finally done. I tried this and it worked. Thank you to all of you
this is what I have done:
...
const USERID_STORED = "userid_stored";
const GSM_STORED = "gsm_stored";
...
class ScoreList extends React.Component {
constructor(props) {
super(props)
this.state = { infos: [], userId: '', gsmStored: '', }
}
componentWillMount() {
AsyncStorage.getItem(USERID_STORED)
.then(userId => {
this.setState({ userId: userId});
this.getScoreFromAPI(this.state.userId).then(data => {
this.setState({ infos: data });
});
});
AsyncStorage.getItem(GSM_STORED)
.then(gsmStore => {
this.setState({ gsmStored: gsmStore});
});
}
getScoreFromAPI (userId) {
let formData = new FormData();
formData.append('userId', userId);
formData.append('key', '***');
return fetch('https://***',{
method : 'POST',
headers : {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data'
},
body : formData
} )
.then((response) => {
return response.json()
})
.catch((error) => console.log("l'erreure est: " + error))
};