I get undefined when reading my response but there is a response in React.js - node.js

I can't figure it out, the answer comes in the network table but when I want to console.log it, this will display undefined. Do you have any idea why? I attach the pictures and the code.
Here is a image with my codes and response
Here is the code - first one is where I send the response. As I said, it's going well on network tab, I get a 200 status.
export const getAccountStatus = async (req, res) => {
const user = await User.findById(req.user._id).exec();
const account = await stripe.accounts.retrieve(user.stripe_account_id);
// console.log("user account retrieve", account);
const updatedUser = await User.findByIdAndUpdate(
user._id,
{
stripe_seller: account
},
{ new: true }
)
.select("-password")
.exec();
console.log(updatedUser);
res.send(updatedUser);
};
Here is the page where i want to console.log it:
const StripeCallback = ({ history }) => {
const { auth } = useSelector(state => ({ ...state }));
const dispatch = useDispatch();
useEffect(() => {
if (auth && auth.token) accountStatus();
}, [auth]);
const accountStatus = async () => {
try {
const res = await getAccountStatus(auth.token);
console.log(res);
} catch (err) {
console.log(err);
}
};
return <div>test</div>;
};
Ang here is the Axios.post (which is working well as I know):
export const getAccountStatus = async token => {
await axios.post(
`${process.env.REACT_APP_API}/get-account-status`,
{},
{
headers: {
Authorization: `Bearer ${token}`
}
}
);
};
Thank you!

getAccountStatus doesn't have a return statement, so res in const res = await getAccountStatus(auth.token); will always be undefined.
export const getAccountStatus = async token => {
return axios.post( // <----- added return
`${process.env.REACT_APP_API}/get-account-status`,
{},
{
headers: {
Authorization: `Bearer ${token}`
}
}
);
};

Related

Jest run async endpoints beforeall, afterall tests

[Junior dev!!]
->Node v18.08
->jest 29.0.1
->MySQL
Hi i m running several jest test in diferent folders of each endpoint on my API. I have several files where i m creating an account => test several endpoints => clean DB.. I have at least 14 files like these. So.. When an endpoint in those 14 file is not working the test doesn't go until the end and clean the DB so i need to go back and change the user name.. A clearly waste of time..
I'm learning about the Hook beforeAll and afterAll but they are not working.
i will show here my code without the hooks (test working)
const axios = require("axios");
const API_URL = process.env.API_TEST_URL;
let TOKEN;
//Creating User
test("POST test register user", async () => {
const data = {
pseudo: "TEST",
password: "123",
date: "2022-08-29 16:31:25",
};
const url = `${API_URL}/register`;
const response = await axios.post(url, data);
expect(response.status).toBe(200);
expect(response.data).toHaveProperty("token");
TOKEN = response.data.token;
});
//Endpoints to test
test("POST/test", async () => {
const url = `${API_URL}/data/actions`;
const data = {
action: "running",
date: "2021-09-30 18:14:24",
};
const headers = { Authorization: `Bearer ${TOKEN}` };
const response = await axios.post(url, data, { headers });
expect(response.status).toBe(200);
});
//Deleting all info from DB
test("DELETE test account", async () => {
const url = `${API_URL}/user/delete/all-data`;
const headers = { Authorization: `Bearer ${TOKEN}` };
const response = await axios.delete(url, { headers });
expect(response.status).toBe(200);
});
And when i want to add the hooks doesn't work
const axios = require("axios");
const API_URL = process.env.API_TEST_URL;
let TOKEN;
//creating before all an user
beforeAll(() => {
test("POST test register user", async () => {
const data = {
pseudo: "TEST",
password: "123",
date: "2022-08-29 16:31:25",
};
const url = `${API_URL}/register`;
const response = await axios.post(url, data);
expect(response.status).toBe(200);
expect(response.data).toHaveProperty("token");
TOKEN = response.data.token;
});
});
//testing endpoints
test("POST/action test", async () => {
const url = `${API_URL}/data/actions`;
const data = {
action: "running",
date: "2021-09-30 18:14:24",
};
const headers = { Authorization: `Bearer ${TOKEN}` };
const response = await axios.post(url, data, { headers });
expect(response.status).toBe(200);
});
// if the endpoint doesn't work afterAll clean all DB
afterAll(() => {
test("DELETE test account", async () => {
const url = `${API_URL}/user/delete/all-data`;
const headers = { Authorization: `Bearer ${TOKEN}` };
const response = await axios.delete(url, { headers });
expect(response.status).toBe(200);
});
});
what do you think. Could you help me ? Because the info on jest is only showing how to do it with a function.. Can we test something inside beforeAll & afterAll ??
I have something similar in a project that I'm working on.
I had to make sure that the beforeAll was an async function and put the await.
beforeAll(async () => {
connection = await createConnection();
await connection.runMigrations();
const id = uuidv4();
const password = await hash('admin', 8);
await connection.query(
`insert into users (id, name, email, password, is_admin, created_at, driver_license)
values ('${id}', 'Admin', 'admin#test.com.br', '${password}', true, 'now()', 'XXXXXXX')`
);
});
afterAll(async () => {
await connection.dropDatabase();
await connection.close();
});
Another thing is that I have done a test using a test function inside the beforeAll and it has returned an error, so maybe just executing the post without the test may work.
Edit: Reading the docs about the test inside the beforeAll and beforeEach, it says that you can not use a test inside it.

How to update data in mongodb database and show in ui

Client-side code...!!!
I want to update the quantity by clicking the Delivered button...
In this section have quantity that i'm show bring database.
const [reload, setReload] = useState(true);
const [stock, setStock] = useState({});
const { _id, quantity } = stock;
useEffect(() => {
const url = `http://localhost:5000/stock/${inventoryId}`;
fetch(url)
.then((res) => res.json())
.then((data) => setStock(data));
}, [reload]);
In this function I want to update quantity that i'm decrising by clicking button
const handleDelivered = () => {
const updateQuantity = parseInt(quantity) - 1; // *actually I want to decrise quantity by clicking Delivered button*
const url = `http://localhost:5000/stock/${inventoryId}`;
fetch(url, {
method: 'PUT',
headers: {
'content-type': 'application/json',
},
body: JSON.stringify(updateQuantity), // *I don't know it's right or wrong and it's so important*
})
.then((res) => res.json())
.then((data) => {
setReload(!reload);
setStock(data);
console.log(data);
});
};
return <button onClick={handleDelivered}>Delivered</button>
Server-side code...!!!
On server-side I want to update just the quantity value...
app.put('/stock/:id', async (req, res) => {
const id = req.params.id;
const updateQuantity = req.body;
const filter = { _id: ObjectId(id) };
const options = { upsert: true };
const updateDoc = {
$set: {
updateQuantity, // *I'm not sure how to set it database. But I want to update quantity value*
},
};
const result = await stockCollection.updateOne(filter, updateDoc, options);
res.send(result);
});
You need to set the updatedQuantity on the "quantity" field of the database. You need to change the "updateDoc" object like this in your server-side code:
const updateDoc = {
$set: {
quantity: updateQuantity,
},
};
Hope this should work.
Client-side code
const handelUpload = (e) => {
e.preventDefault();
const storeQuantity = parseInt(product?.quantity);
const newQuantity = parseInt(e.target.quantity.value);
const quantity = storeQuantity + newQuantity;
if (quantity > 0) {
fetch(`http://localhost:5000/stock/${inventoryId}`, {
method: "PUT",
headers: {
"Content-type": "application/json; charset=UTF-8",
},
body: JSON.stringify({ quantity }),
})
.then((response) => response.json())
.then((data) => {
console.log("success", data);
alert("users added successfully!!!");
e.target.reset();
setIsreload(!isReload);
});
} else {
console.log("input number");
}
};
Server side code api
app.put("/stock/:id", async (req, res) => {
const id = req.params.id;
const updatedProduct = req.body;
console.log(updatedProduct.quantity);
console.log(typeof updatedProduct.quantity);
const filter = { _id: ObjectId(id) };
const options = { upsert: true };
const updatedDoc = {
$set: {
// name: updatedProduct.name,
// email: updatedProduct.email,
quantity: updatedProduct.quantity,
// price: updatedProduct.price,
},
};
const result = await stockCollection.updateOne(filter,updatedDoc,options
);
res.send(result);
});

React Express How to send multiple service data to the same controller at backend

I am trying to filter posts according to some parameters and I am trying to send the data to the same controller which Gets the posts.
Get Posts service:-
const getPosts = async (page, token) => {
const config = {
headers: {
Authorization: `Bearer ${token}`,
},
params: {
page: page,
},
};
const response = await axios.get(API_URL, config);
return response.data;
};
here the Page parameter is for pagination.
Filter Posts service:-
const filterPosts = async (filterData, token) => {
const config = {
headers: {
Authorization: `Bearer ${token}`,
},
data: {
filterData,
},
};
const response = await axios.get(API_URL, config);
return response.data;
}
Route to Get and Filter Posts:-
router.route("/").get(protect, getPosts);
Get Posts Controller:-
const getPosts = asyncHandler(async (req, res) => {
console.log("filter data:- ", req.body); // This Part is undefined.
//pagination
const PAGE_SIZE = 6;
const PAGE = parseInt(req.query.page || "0");
const total = await Post.countDocuments({ user: req.user.id });
const AllPosts = await Post.find({ user: req.user.id })
.limit(PAGE_SIZE)
.skip(PAGE_SIZE * PAGE)
.sort({ createdAt: -1 });
const totalPages = Math.ceil(total / PAGE_SIZE);
res.status(200).json({ totalPages, Allposts });
});
How do I send filter data and pagination parameter to the same getPosts controller?
filter data is undefined

Execute function from object property

i have a little problem with my code.
My expectation is, when i get the object reqHeaders to the function getQueryData
i want that the property UUID will execute the function createToken().
currently, when i running the program, it happens only at the init( first time ).
const createToken = () => {
// some logics...
return `${token}`;
};
const reqHeaders = {
UUID: **createToken()**,
"Content-Type": "application/json;charset=UTF-8"
};
const getQueryData = query => {
return axiosInstance
.post("/someAddress", { selectQuery: query }, { headers: **reqHeaders** })
.then(response => {
// some logs...
return response.data;
})
.catch(error => {
//some logs....
return error;
});
}
};
module.exports = getQueryData;
thank you,
Raz.
The solution is to move the object creation inside the body of the function.
const createToken = () => {
// some logics...
return `${token}`;
};
const getQueryData = query => {
return axiosInstance
.post("/someAddress", { selectQuery: query }, { headers: {
UUID: **createToken()**,
"Content-Type": "application/json;charset=UTF-8"
} })
.then(response => {
// some logs...
return response.data;
})
.catch(error => {
//some logs....
return error;
});
}
};
module.exports = getQueryData;
Now each time you run the function new req headers will be created and hence the UUID. What you did previously created an object once and then use the same object for each function call.

How to receive re-requested data when data requested by mounted() is re-requested by aixos interceptor

the code below is the first request for get list data
mounted() {
this.getList()
},
methods: {
handleClick(row) {
console.log(row.id)
console.log(row.url)
this.$router.push({ name: 'Main', query: { id: row.id } })
},
getList() {
axios
.get('/api/v1/requests/all', {
params: {
userId: this.$store.state.userInfo.id,
},
})
.then(response => {
let moment = require('moment')
for (var item of response.data.data) {
item.createdAt = moment(item.createdAt).format(
'YYYY-MM-DD HH:mm:ss',
)
}
this.items = response.data.data
})
.catch(error => {
console.log(error)
})
}
my interceptor
axios.interceptors.response.use(
function (response) {
return response
},
async function (error) {
const originalRequest = error.config
if (error.response.status === 401 && !originalRequest._retry) {
error.response.config._retry = true
sessionStorage.removeItem('access-token')
let headers = {
grant_type: 'refresh_token',
Authorization: sessionStorage.getItem('refresh-token'),
}
axios
.post('/api/v1/users/refresh_token', {}, { headers: headers })
.then(response => {
let token = response.data.data
sessionStorage.setItem('access-token', token)
originalRequest.headers['Authorization'] = token
originalRequest.headers['grant_type'] = 'grant_type'
return axios.request(originalRequest)
})
.catch(error => {
console.log(error)
alert('blablabla.')
})
}
return Promise.reject(error)
},
)
the flow is i understand
1.token expired
2.move to list page
3.mounted hook is request data
4.getList -> axios get('~~request/all')
5.interceptor->axios post('~~~refresh_token')
6.re request with new token(request/all)
7.re request is 200, but not update list page
i'd really appreciate your help :)
Seems like you need to return the second request (await for result and return). Right now the result of second request seems to be ignored
axios.interceptors.response.use(
function (response) {
return response;
},
async function (error) {
const originalRequest = error.config;
if (error.response.status === 401 && !originalRequest._retry) {
error.response.config._retry = true;
sessionStorage.removeItem("access-token");
let headers = {
grant_type: "refresh_token",
Authorization: sessionStorage.getItem("refresh-token"),
};
const [secondError, res] = await axios // await here
.post("/api/v1/users/refresh_token", {}, { headers: headers })
.then(async (response) => {
let token = response.data.data;
sessionStorage.setItem("access-token", token);
originalRequest.headers["Authorization"] = token;
originalRequest.headers["grant_type"] = "grant_type";
return [null, await axios.request(originalRequest)];
})
.catch((err) => {
console.log(err);
alert("blablabla.");
return [err, null];
});
// Handle here
if(secondError) {
return Promise.reject(secondError);
}
return Promise.resolve(res)
}
return Promise.reject(error);
}
);
The above solution worked for me perfectly. here's the modified code that I used for my requirement.
export default function axiosInterceptor() {
//Add a response interceptor
axios.interceptors.response.use(
(res) => {
// Add configurations here
return res;
},
async function (error) {
const originalRequest = error.config;
let secondError, res
if (error.response.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
[secondError, res] = await axios({
method: "POST",
url: `${baseURL}/account/token/refreshtoken`,
withCredentials: true,
headers: { "Content-Type": "application/json" },
})
.then(async (response) => {
//handle success
return [null, await axios.request(originalRequest)];
}).catch(function (error) {
console.error(error)
});
}
if (secondError) {
return Promise.reject(secondError);
}
return Promise.resolve(res)
}
);
}

Resources