On a vue application, on a component, calling API to get some data... the problem is that getting undefined, before the call ends... Possible needed aync/await but getting error when adding
//component code (login.vue)
import store from "#/store";
const { response, error } = store.postTO(url, [{id: "button1"}, {id: "button2"}, {id: "button3"}]);
if (response) {
console.log(response);
} else {
console.warn(error);
}
//store.js
export default {
user : null,
postTO
}
function postTO(url, postData) {
const requestOptions = {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: JSON.stringify(postData)
};
return fetch(url, requestOptions).then(response =>
response.json().then(data => ({
data: data,
status: response.status
})
).then(res => {
console.log(res.data);
return {response : res.data, error : "test"};
}))
.catch(error => {
return {response : "test", error : error};
});
}
illustrated
In the component you have to wait for the fetch by putting an await before the store.posTo
Related
I am trying to do a helper function to check if login or not in react and nodejs... in nodejs everything is fine but I have problems at reactside to get value outside of function with return:
return output always = undefined ...
Here is the function;
note: console.log (response) = {status: 200, data: true, error:
false}
import axios from "axios";
import { useState,useEffect } from 'react';
export const AuthController = (event) => {
let data = {data : localStorage.getItem("imtakilogintoken")}
async function getData() {
try {
let res = await axios({
url: 'http://localhost:3005/profile',
method: 'post',
timeout: 8000,
data :data,
headers: {
'Content-Type': 'application/json',
}
})
return {
status : res.status,
data : res.data,
error : false
}
}
catch (err) {
return {
status : false,
data : false,
error : err
}
}
}
var output;
useEffect(() => {
getData().then(response => {
console.log (response)
output = response;
})
}, []);
return output;
}
For your kind information useEffect() is async function, the control first going to return statement and at this time return output (undefined) having undefined.
I think here no need to wrap your function into useEffect() instead just return from then only. so code would look like below.
import axios from "axios";
import { useState,useEffect } from 'react';
export const AuthController = (event) => {
let data = {data : localStorage.getItem("imtakilogintoken")}
async function getData() {
try {
let res = await axios({
url: 'http://localhost:3005/profile',
method: 'post',
timeout: 8000,
data :data,
headers: {
'Content-Type': 'application/json',
}
})
return {
status : res.status,
data : res.data,
error : false
}
}
catch (err) {
return {
status : false,
data : false,
error : err
}
}
}
//var output;
getData().then(response => {
console.log (response)
return response;
}).catch(err=>{
return err;
})
}
I think the problem itself is how you are trying to reach the data, on react I will recommend you to create a custom hook that you can implement on any component that loads later on the app, something like this:
import { useState, useCallback } from "react";
import axios from "axios";
const useAuthControl = () => {
const [hasResponse, setResponse] = useState(null);
const getData = useCallback(
async (data) => {
try {
let res = await axios({
url: 'http://localhost:3005/profile',
method: 'post',
timeout: 8000,
data :data,
headers: {
'Content-Type': 'application/json',
}
})
setResponse({
status : res.status,
data : res.data,
error : false
})
}
catch (err) {
setResponse({
status : false,
data : false,
error : err
})
}
},
[]
);
return [getData, {hasResponse}];
};
export default useAuthControl;
I am trying to get the status of a request I do from a React website I am working on, using axios to fetch make requests to a RoR API I developed. I would like to confirm that the POST request succeeded by accessing the status value from this (which is the output of a console.log(response):
Promise { <state>: "pending" }
<state>: "fulfilled"
<value>: Object { data: {…}, status: 201, statusText: "Created", … }
config: Object { url: "pathname", method: "post", data: "{\"user\":{\"email\":\"lou10#email.com\",\"username\":\"lou10\",\"password\":\"azerty\"}}", … }
data: Object { data: {…} }
headers: Object { "cache-control": "max-age=0, private, must-revalidate", "content-type": "application/json; charset=utf-8" }
request: XMLHttpRequest { readyState: 4, timeout: 0, withCredentials: false, … }
status: 201
statusText: "Created"
<prototype>: Object { … }
index.jsx:51:11
But when I try a console.log(response.status) all I get is an undefined.
Here is the code :
import axios from 'axios';
import { BASE_URL } from "./config.js";
const post = async (
endpoint,
body = null,
jwt_token = null,
header = { "Content-Type": "application/json" }) => {
let opt = header;
if (jwt_token){
opt["Authorization"] = jwt_token
}
try {
const response = await axios.post(BASE_URL + endpoint, body, { headers: opt })
return response
} catch (err) {
console.error(`An error occurred while trying to fetch ${endpoint}. ${err}`);
}
}
export default post;
const handleSignup = async ({ email, username, pwd }) => {
let body = {
user: {
email: email,
username: username,
password: pwd
}
};
return await post("/users", body);
};
useEffect(() => {
if (passwordCheck === false) {
console.log("Passwords do not match");
} else if (passwordCheck === true && userData) {
const response = await handleSignup(userData);
console.log(response.status);
// history.push({ pathname: "/", state: response.status });
}
}, [passwordCheck, userData]);
I am thinking to change the response from my API, but I really doubt it is the right approach.
Edit 1: adding some complementary code
you have to declare the function you give in parameter to useEffect as async to be able to use await inside for your async function handleSignup
useEffect(async () => {
if (passwordCheck === false) {
console.log("Passwords do not match");
} else if (passwordCheck === true && userData) {
const response = await handleSignup(userData);
console.log(response.status);
// history.push({ pathname: "/", state: response.status });
}
}, [passwordCheck, userData]);
I have already define error initially, but now I don't know why show me error like this
fetch data from backend code:
auth.js file
import fetch from "isomorphic-fetch";
import { API } from "../config";
export const signup = (user) => {
return fetch(`${API}/signup`, {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify(user),
})
.then((res) => {
return res.json();
})
.catch((err) => {
console.log(err);
});
};
I have link connection inside API I'm sure is it ok.
After that when i submit my signup from then show me error, signup handleSubmit code:
signupComponent.js file
const handleSubmit = (e) => {
e.preventDefault();
//console.table({ name, email, password, error, loading, message, showForm });
setValues({ ...values, loading: true, error: false });
const user = { name, email, password };
signup(user).then((data) => {
try {
if (data.error) {
setValues({ ...values, error: data.error, loading: false });
} else {
setValues({
...values,
name: "",
email: "",
password: "",
error: "",
loading: false,
message: data.message,
showForm: false,
});
}
} catch (err) {
console.log(err);
}
});
};
I'm sure my internet connection is ok.
I don't know where is problem.
Any suggestion please.
auth.js file updated:
Return the err from catch
import fetch from "isomorphic-fetch";
import { API } from "../config";
export const signup = (user) => {
return fetch(`${API}/signup`, {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify(user),
})
.then((res) => {
return res.json();
})
.catch((err) => {
return err;
});
};
You have a chain of callbacks
fetch().then().catch()
in your .then() you return the data but in your .catch() you return nothing.
Therefore your outer chain will try to process undefined incase the fetching failed.
signup().then(
(data) => ... data.error // data is undefined
)
I have solve my problem by this way:
used try catch block for find problem
In the catch block used .catch((err) => { return err; });
And make sure API connected succesfully
After that run my backend server
Then run my frontend.
I've this code into pages folder on my NextJS environment. It gets data calling an external API Rest, and it's working because the console.log(response); line show me by console the Json API response. The problem I've is that I get this error in browser:
TypeError: Cannot read property 'json' of undefined
Corresponding with this line code:
const data = await res.json();
This is the complete file with the code:
import React from "react";
import fetch from "node-fetch";
const getFetch = async (invoicesUrl, params) => {
fetch(invoicesUrl, params)
.then((response) => {
return response.json();
})
.then((response) => {
console.log(response);
})
.catch((err) => {
console.log(err);
});
};
export const getServerSideProps = async () => {
const invoicesUrl = "https://192.168.1.38/accounts/123456";
const params = {
method: "get",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
};
const res = await getFetch(invoicesUrl, params);
const data = await res.json();
console.log("Data Json: ", data);
return { props: { data } };
};
This is the Json API response that I see by console:
{
account: [
{
id: '7051321',
type: 'probe',
status: 'open',
newAccount: [Object],
lastDate: '2020-07-04',
taxExcluded: [Object],
totalRecover: [Object],
documentLinks: []
},
]
}
Any idea how can I solve it?
Thanks in advance.
UPDATE
Here the code working good:
import React from "react";
import fetch from "node-fetch";
const getFetch = async (invoicesUrl, params) => {
return fetch(invoicesUrl, params);
};
export const getServerSideProps = async () => {
const invoicesUrl = "https://192.168.1.38/accounts/123456";
const params = {
method: "get",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
};
try {
const res = await getFetch(invoicesUrl, params);
const data = await res.json();
console.log("Data JSON: ", data);
return { props: { data } };
} catch (error) {
console.log("Data ERROR: ", error);
}
};
There are a couple of things you have to change.
const getFetch = async (invoicesUrl, params) => {
fetch(invoicesUrl, params)
.then((response) => {
return response.json();
})
.then((response) => {
console.log(response);
return response; // 1. Add this line. You need to return the response.
})
.catch((err) => {
console.log(err);
});
};
export const getServerSideProps = async () => {
const invoicesUrl = "https://192.168.1.38/accounts/123456";
const params = {
method: "get",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
};
const data = await getFetch(invoicesUrl, params);
// const data = await res.json(); 2. Remove this you have already converted to JSON by calling .json in getFetch
console.log("Data Json: ", data); // Make sure this prints the data.
return { props: { data } };
};
You have return statement in wrong place.
When the function is expecting a return. You need to return when the statements are executed not inside the promise then function because it is an async callback function which is not sync with the statement inside getFetchfunction. I hope i have made things clear. Below is the code which will any how return something
import React from "react";
import fetch from "node-fetch";
const getFetch = async (invoicesUrl, params) => {
return fetch(invoicesUrl, params);
};
export const getServerSideProps = async () => {
const invoicesUrl = "https://192.168.1.38/accounts/123456";
const params = {
method: "get",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
};
try{
const res = await getFetch(invoicesUrl, params);
console.log("Data Json: ", res);
}catch(error){
console.log("Data Json: ", error);
}
return { props: { res } };
};
I am writing a mobile application with using React Native. At some part, I need to send a post request and get response including the error part. So, for some certain input, API(my own) returns 409 with a message. Example return:
{
"status": 409,
"message": "E-mail is already exists!"
}
Here, I want to take that message and show to the user. This is what I tried:
UserService.signup({ fullName, email, username, password })
.then(response => {
this.setState({ signUp: true });
if (response.result) {
Toast.show(messages.successfulSignUp, {
backgroundColor: "green",
duration: Toast.durations.LONG,
position: Toast.positions.TOP
});
this.props.navigation.navigate("SignIn");
} else {
}
})
.catch(error => {
Toast.show(error.message, {
backgroundColor: "red",
duration: Toast.durations.LONG,
position: Toast.positions.TOP
});
this.setState({ signUp: false });
});
I tried error.message, error.response, error, error.data keys, but it always says TypeError: undefined is not an object (evaluating 'error.message'). So, how can I get the message from error object?
Edit: This is how I send the request:
import { post } from "./api";
export default {
signup: ({ fullName, email, username, password }) => {
return post("/user/register", { fullName, email, username, password });
}
};
export const request = config => {
return new Promise((resolve, reject) => {
axiosInstance
.request({
url: config.url,
method: config.method || "get",
data: config.body,
headers: {
"Content-Type": "application/json",
"X-Auth-Token": store.getState().auth.token
}
})
.then(response => {
resolve(response.data);
})
.catch(error => {
reject(error.data);
});
});
};
export const post = (url, body = {}) => {
return request({
url,
body,
method: "post"
});
};
Finally I solved this issue. I had to change my request method and the way I reach out to the error:
export const request = (config) => {
return new Promise((resolve, reject) => {
axiosInstance.request({
url: config.url,
method: config.method || 'get',
data: config.body,
headers: {
'Content-Type': 'application/json',
'X-Auth-Token': store.getState().auth.token,
}
}).then(response => {
resolve(response.data)
}).catch(error => {
reject(error.response)
})
})
}
// This is how reach out to the error message:
console.log(error.data.message);
Depending on what the backend returns, the error message in axios is in response.data of the error object.
.catch(error => {
const errResponse = (error && error.response && error.response.data)
|| (error && error.message);
reject(errResponse);
});