I am getting TypeError: Failed to fetch while using this function - node.js

I am trying to make a full stack Transport management system with mern but it runs fine for 15s and after that TypeError: Failed to fetch comes in and it increases exponentially in my console.
useEffect(() => {
const fetchBus = async () => {
try{
const response = await fetch("/api/buses");
const json = await response.json();
if (response.ok) {
dispatch({ type: "SET_BUS", payload: json });
}
}
catch(error){
console.log(error)
}
};
fetchBus();
}, [handleOwnership,handleAvailable]);

As fetch() and response.json() both are asynchronous tasks and both returns a Promise.You need to parse json data inside an if(response.ok){} block:
Replace:
useEffect(() => {
const fetchBus = async () => {
try{
const response = await fetch("/api/buses");
//const json = await response.json();//Not here
if (response.ok) {
const json = await response.json();//But Here
dispatch({ type: "SET_BUS", payload: json });
}
}
catch(error){
console.log(error)
}
};
fetchBus();
}, [handleOwnership,handleAvailable]);
Fetch JSON GET Request:
let url = 'https://someurl.com';
let response = await fetch(url);
let responseOK = response && response.ok;
if (responseOK) {
let data = await response.json();
// do something with data
}
Fetch JSON POST Request:
let url = 'https://someurl.com';
let options = {
method: 'POST',
mode: 'cors',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json;charset=UTF-8'
},
body: JSON.stringify({
property_one: value_one,
property_two: value_two
})
};
let response = await fetch(url, options);
let responseOK = response && response.ok;
if (responseOK) {
let data = await response.json();
// do something with data
}

I figured it out. I was getting into a death-loop because I added functions in my dependencies but I learned that one should never do that instead of function add variables or arrays or primitives in dependencies.
For me I used use-state (variable) in dependencies instead of functions

Related

Remix Run UploadHandler Using Data for WhatsApp API Media Upload

I am attempting to use a form in Remix to add a file and then upload that file to WhatsApp using their Cloud API Media Upload endpoint. Below is my initial code within the action. The current error I am receiving is message: '(#100) The parameter messaging_product is required.. I feel like this error may be misleading based off the form data I have appended with the "messaging_product".
export async function action({ request, params }: ActionArgs) {
const uploadHandler = unstable_composeUploadHandlers(
async ({ name, contentType, data, filename }) => {
const whatsAppPhoneId = process.env.WHATSAPP_PHONE_ID;
const whatsAppToken = process.env.WHATSAPP_ACCESS_TOKEN;
const dataArray1 = [];
for await (const x of data) {
dataArray1.push(x);
}
const file1 = new File(dataArray1, filename, { type: contentType });
const graphApiUrl = `https://graph.facebook.com/v15.0/${whatsAppPhoneId}/media`;
const formData = new FormData();
formData.append("file", file1);
formData.append("messaging_product", "whatsapp");
formData.append("type", contentType);
try {
const imageMediaResponse = await fetch(graphApiUrl, {
method: "POST",
headers: {
Authorization: `Bearer ${whatsAppToken}`,
"Content-Type": "multipart/form-data",
},
body: formData,
});
const imageMedia = await imageMediaResponse.json();
return imageMedia?.id;
} catch (error) {
console.error(error);
}
const whatsAppMediaId = await uploadWhatsAppImageMedia(
whatsAppPhoneId,
whatsAppToken,
data,
filename,
contentType
);
}
);
const formData = await unstable_parseMultipartFormData(
request,
uploadHandler
);
}

An problem occur when submit a GET Request by node-fetch

I am using node-fetch to fetch data from REST API.
Here is my code:
this.getUserList = async (req, res) => {
const fetch = require('node-fetch');
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
let params = {
"list_info": {
"row_count": 100
}
}
fetch('https://server/api/v3/users?input_data=' + JSON.stringify(params), {
headers:{
"TECHNICIAN_KEY": "sdfdsfsdfsd4343323242324",
'Content-Type': 'application/json',
},
"method":"GET"
})
.then(res => res.json())
.then(json => res.send(json))
.catch(err => console.log(err));
}
It works fine.
However, if I change the following statement:
let params = {"list_info":{"row_count": 100}}
To
let params = {"list_info":{"row_count": 100}, "fields_required": ["id"]}
It prompts the following error message:
FetchError: invalid json response body at https://server/api/v3/users?input_data=%7B%22list_info%22:%7B%22row_count%22:100%7D,%22fields_required%22:[%22id%22]%7D reason: Unexpected end of JSON input`
The problem is that you are not URL-encoding your query string. This can be easily accomplished using URLSearchParams.
Also, GET requests do not have any request body so do not need a content-type header. GET is also the default method for fetch()
const params = new URLSearchParams({
input_data: JSON.stringify({
list_info: {
row_count: 100
},
fields_required: ["id"]
})
})
try {
// 👇 note the ` quotes
const response = await fetch(`https://server/api/v3/users?${params}`, {
headers: {
TECHNICIAN_KEY: "sdfdsfsdfsd4343323242324",
}
})
if (!response.ok) {
throw new Error(`${response.status}: ${await response.text()}`)
}
res.json(await response.json())
} catch (err) {
console.error(err)
res.status(500).send(err)
}

I get undefined when reading my response but there is a response in React.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}`
}
}
);
};

Postman can upload file to a Node api. But Not with React

Redux Code
export const uploadImage = data => async dispatch => {
const config = {
headers: {
"Content-Type": "multipart/form-data"
}
};
try {
const res = await axios.post("/api/profile/upload", data, config);
// const res = await axios.post("/api/profile/upload", data, {
// headers: {
// "Content-Type": "multipart/form-data"
// }
// });
console.log(res);
dispatch({
type: AVATAR_UPLOAD,
payload: res.data
});
} catch (err) {
const errors = err.response.data.errors;
if (errors) {
errors.forEach(error => dispatch(setAlert(error.msg, "danger")));
}
dispatch({
type: PROFILE_ERROR,
payload: { msg: err.response.statusText, status: err.response.status }
});
}
};
React Code
const data = new FormData();
data.append("file", avatar);
uploadImage(data);
I get bad request message, req.files is empty
I try to upload file with Postman same configuration,it seems api works but can't upload with react formdata.
Any idea would be appreciated. Thanks in advance
try doing this:
const formData = new FormData();
formData.append('file', file);
const res = await axios.post("/api/profile/upload", formData, config);

How to show the success response from node server on react-redux framework

I am making a demo react-redux app for the basic understanding of redux and its server is made on nodeJS. I have made a simple form which gets submitted and the server response is res.send('FORM SAVED'). In front-end, I make the post request but is not able to see the response that returns, be it the success response.
My server controller that responds when form details are saved.
export const postData = (req, res) => {
let p = new PostData();
p.name = req.body.name;
p.emp_id = req.body.emp_id;
p.age = req.body.age;
p.dept = req.body.dept;
p.phone = req.body.phone;
p.gender = req.body.gender;
p.save(((err) => {
if (err){res.send(`Error in uploading: ${err}`);}
else {res.send('Form saved');}
}));
}
This is my action:-
export const createPost = postData => dispatch => {
fetch(`${Config.address}/post`, {
method: 'POST',
headers:{
'Content-Type': 'application/json'
},
body: JSON.stringify(postData)
})
.then((post) => {
console.log('post:', post);
dispatch({
type: NEW_POST,
payload: post
})
})
}
This is how I call this in component after clicking submit:-
onSubmit = (e) => {
e.preventDefault();
let postData = {
name: this.state.name,
emp_id: this.state.emp_id,
dept: this.state.dept,
gender: this.state.gender,
age: this.state.age,
phone: this.state.phone
}
this.props.createPost(postData);
}
I want to get the response string ('Form saved') but I don't know how to read that. Can anyone help? Thanks in advance
fetch returns a raw response object. To get an expected data you should call a .json() method on raw response object which is returned by fetch, like below:
export const createPost = postData => dispatch => {
fetch(`${Config.address}/post`, {
method: 'POST',
headers:{
'Content-Type': 'application/json'
},
body: JSON.stringify(postData)
})
.then(response => response.json()) // add this line
.then((post) => {
console.log('post:', post); // you should get an object with `Form saved` or something similar to it
dispatch({
type: NEW_POST,
payload: postData // replace it to the input parameter
})
})
}
Using async/await it becomes more readable:
export const createPost = (postData) => async (dispatch) => {
// send postData to server
const rawResponse = await fetch(`${Config.address}/post`, {
method: 'POST',
headers:{
'Content-Type': 'application/json'
},
body: JSON.stringify(postData)
});
// we are done with server but we need one more step
// turn a raw response to readable JS object
const message = await rawResponse.json()
// message from server response
console.log('Message ', message);
// store same object as we sent to server in redux store
dispatch({ type: NEW_POST, payload: postData });
}
Hope it helps

Resources