I tried to delete the item >>But when I click on the button and function does not work!!!!
Deleting in backend works but in frontend does not work!!
This is my function:
deleteblog = async id => {
// this.setState({ isLoading: true });
try {
const response = await fetch(
`http://localhost:8080/blog/delete/${id}`
);
const answer = await response.json();
if (answer.success) {
const blog = this.state.blog.filter(
contact => contact.id !== id
);
toast(`blog with id ${id} was successfully deleted!`);
this.setState({ blog });
} else {
console.log();
false });
}
} catch (err) {
console.log("error", err);
false });
}
};
This is the button:
<button type="button" onClick={this.deleteblog} class="btn btn-danger btn-rounded btn-sm my-0">delete</button>
This error that is showed in console log
GET http://localhost:8080/blog/delete/undefined 500 (Internal Server Error)
error SyntaxError: Unexpected token < in JSON at position 0
at BlogAdmin.deleteblog (Blogadmin.js:104)
And this >>> Blogadmin.js:104
====> const answer = await response.json();
The response might be an HTML instead of a JSON response, it is better to have more check than accessing response.json() directly as that will be dangerous and easily throw you a Syntax Error.
You can check the response through the browser development console -> Network tab, and see the request and response:
or adding console.log to the response for debugging.
After all, you should improve the handling for reading the response data, and your application will be fine:
deleteblog = async id => {
this.setState({ isLoading: true });
try {
const response = await fetch(`http://localhost:8080/blog/delete/${id}`);
// For debugging
console.log('response', JSON.stringify(response));
const answer = response && typeof response.json === 'function' && response.json();
if (answer.success) {
const blog = this.state.blog.filter(contact => contact.id !== id);
toast(`blog with id ${id} was successfully deleted!`);
this.setState({ blog });
}
else {
toast(`Error: blog with id ${id} was unable to delete!`);
this.setState({ isLoading: false });
}
}
catch (err) {
console.error('Unexpected error occurred:', err);
this.setState({ isLoading: false });
}
};
Related
I try to explain the problem.in App.js I have Function getUser .when call this function.in first request get 401 error . For this reason in axios.interceptors.response I receive error 401.At this time, I receive a token and repeat my request again.And it is done successfully.But not return response in Function getUser.
I have hook for authentication and send request.
import React from "react";
import axios from "axios";
const API_URL = "http://127.0.0.1:4000/api/";
function useJWT() {
axios.interceptors.request.use(
(request) => {
request.headers.common["Accept"] = "application/json";
console.log("request Send ");
return request;
},
(error) => {
return Promise.reject(error);
}
);
axios.interceptors.response.use(
(response) => {
console.log("answer = ", response);
return response;
},
(error) => {
if (error?.response?.status) {
switch (error.response.status) {
case 401:
refreshToken().then((responseTwo) => {
return
sendPostRequest(
error.response.config.url
.split("/")
.findLast((item) => true)
.toString(),
error.response.config.data
);
});
break;
case 500:
// Actions for Error 500
throw error;
default:
console.error("from hook interceptor => ", error);
throw error;
}
} else {
// Occurs for axios error.message = 'Network Error'
throw error;
}
}
);
const refreshToken = () => {
const token = localStorage.getItem("refresh");
return axios
.post(API_URL + "token", {
token,
})
.then((response) => {
if (response.data.access) {
localStorage.setItem("access", response.data.access);
}
if (response.data.refresh) {
localStorage.setItem("refresh", response.data.refresh);
}
return response.data;
});
};
function login(email, password) {
return axios
.post(API_URL + "login", {
email,
password,
})
.then((response) => {
if (response.data.access) {
localStorage.setItem("access", response.data.access);
}
if (response.data.refresh) {
localStorage.setItem("refresh", response.data.refresh);
}
return response.data;
});
}
const sendPostRequest = (url, data) => {
console.log(300);
const token = localStorage.getItem("access");
axios.defaults.headers.common["jwt"] = token;
return axios.post(API_URL + url, {
data,
});
};
const logout = () => {
const token = localStorage.getItem("refresh");
return axios
.delete(API_URL + "logout", {
token,
})
.then((response) => {
localStorage.removeItem("access");
localStorage.removeItem("refresh");
});
};
return {
login,
logout,
refreshToken,
sendPostRequest,
};
}
export default useJWT;
In App.js ,I want to repeat the same request again if a 401 error is issued when I read the user information.
The request is successfully repeated but does not return the value.
When first request fail response is return equals null . and in catch when receive 401 error i am send second request but not return response.
I send request below code .
const getUser = () => {
console.log(12);
return sendPostRequest("user");
};
useEffect(() => {
let token = localStorage.getItem("access");
console.log("token = ", token);
if (token != null) {
//Here I have done simulation for 401 error
localStorage.setItem("access", "");
getUser()
.then((response) => {
console.log("response 1= ", response);
})
.catch((exception) => {
console.log("exception = ", exception.toString());
})
.then((response) => {
console.log("response 2= ", response);
});
} else {
navigate("/login");
}
}, []);
Best regards.
I didn't fully understand what exactly you want to do here.
But if you are looking to retry when 401 happens, you could use axios-retry to do it for you.
I'll pass the basics, but you can look more into what this does.
// First you need to create an axios instance
const axiosClient = axios.create({
baseURL: 'API_URL',
// not needed
timeout: 30000
});
// Then you need to add this to the axiosRetry lib
axiosRetry(axiosClient, {
retries: 3,
// Doesn't need to be this, it can be a number in ms
retryDelay: axiosRetry.exponentialDelay,
retryCondition: (error) => {
// You could do this way or try to implement your own
return error.response.status > 400
// something like this works too.
// error.response.status === 401 || error.response.status >= 500;
}
});
Just like in your code, we need to use interceptors if you want to avoid breaking your page, otherwise you can use try catch to catch any errors that may happen in a request.
// It could be something like this, like I said, it's not really needed.
axiosClient.interceptors.response.use(
(success) => success,
(err) => err
);
And finally, you could use the axiosClient directly since it now has your API_URL, calling it like this axiosClient.post('/user').
More or less that's it, you should just debug this code and see what is causing the return value to be null.
I would change these then/catch to be an async/await function, it would be more readable making your debugging easier.
axios-retry example if you didn't understand my explanation.
I find anwser for this question.
When error 401 occurs then create new Promise
I Wrote this code.
case 401:
return new Promise((resolve, reject) => {
refreshToken().then((responseTwo) => {
resolve(
sendPostRequest(
error.response.config.url
.split("/")
.findLast((item) => true)
.toString(),
error.response.config.data
)
);
});
});
This question already has answers here:
loging the response.json() inside the then() method before returning the response.json() promise
(1 answer)
JavaScript fetch - Failed to execute 'json' on 'Response': body stream is locked
(11 answers)
Closed 6 months ago.
I am trying to figure out what change I need to make to my flow where I am triggering a post call and on success return to run another fetch call followed by a 3rd party generated redirect (Stripe). At the moment I am receiving an error message at const session = await response.json()
with the message:
Failed to execute 'json' on 'Response': body stream already read
and I'm not sure how to refactor my code to be able to handle this issue. Can anyone point to what is wrong with my current setup and the rules I might be breaking?
const signUp = (e) => {
e.preventDefault();
if (password === passwordConfirmation) {
axios
.post(
"/api/auth/signup/",
{ email, password, passwordConfirmation },
{
headers: {
"Content-Type": "application/json",
},
withCredentials: true,
}
)
.then((res) => {
const data = res.data;
setUser(data.user);
// Set the error message
if (data.message.status === "error") {
console.log("Error present");
setMessage(data.message);
}
return data.message.status;
})
.then(async (serverMessage) => {
// On successful sigin, redirect to /api/stripe/checkout-session/
if (serverMessage !== "error") {
// Get Stripe.js instance
const stripe = await stripePromise;
const response = await fetch("/api/stripe/checkout-session/", {
method: "POST",
});
console.log(`response: ${response.json()}`);
const session = await response.json();
console.log(`session: ${session}`);
// When the customer clicks on the button, redirect them to Checkout.
const result = await stripe.redirectToCheckout({
sessionId: session.sessionId,
});
// router.push('/api/stripe/checkout-session/')
// router.push('/app/feed/')
}
})
.catch((err) => {
console.log(err);
console.log(err.request);
console.log(err.message);
});
} else {
setMessage({
status: "error",
body: "Passwords do not match. Please try again.",
});
}
};
Do not call .json() twice.
change
console.log(`response: ${response.json()}`);
const session = await response.json();
to
const session = await response.json();
console.log(`response: ${session}`);
you can only read body stream once :) Try this
const signUp = (e) => {
e.preventDefault();
if(password === passwordConfirmation){
axios.post('/api/auth/signup/', { email, password, passwordConfirmation }, {
headers: {
'Content-Type': 'application/json'
},
withCredentials: true
}).then((res) => {
const data = res.data;
setUser(data.user)
// Set the error message
if(data.message.status === 'error'){
console.log('Error present')
setMessage(data.message)
}
return data.message.status
}).then(async (serverMessage) => {
// On successful sigin, redirect to /api/stripe/checkout-session/
if (serverMessage !== 'error'){
// Get Stripe.js instance
const stripe = await stripePromise;
const response = await fetch('/api/stripe/checkout-session/', { method: 'POST' });
const responseBody = await response.json()
console.log(`response: ${responseBody}`);
const session = responseBody;
console.log(`session: ${session}`);
// When the customer clicks on the button, redirect them to Checkout.
const result = await stripe.redirectToCheckout({
sessionId: session.sessionId,
});
// router.push('/api/stripe/checkout-session/')
// router.push('/app/feed/')
}
}).catch((err) => {
console.log(err)
console.log(err.request)
console.log(err.message)
})
} else {
setMessage({
'status': 'error',
'body': 'Passwords do not match. Please try again.'
})
}
}
I'm trying to catch the error this error message from my Rest controller in spring
#GetMapping
public List<Student> getAllStudent() {
throw new IllegalStateException("Opps can not get all students");
// return studentService.getAllStudents();
}
The error is catch in react this way, what I'm trying to do is to show in the console the Error message
import fetch from "unfetch";
const checkStatus = (response) => {
if (response.ok) {
return response;
} else {
let error = new Error(response.statusText);
error.response = response;
response.json().then((e) => {
error.error = e;
});
return Promise.reject(error);
}
};
export const getAllStudents = () =>
fetch("http://localhost:1020/api/students").then(checkStatus);
And then is consume by this method to show it in the console
const fetchAllStudents = () => {
this.setState({
isFetching: true,
});
getAllStudents()
.then((res) =>
res.json().then((students) => {
console.log(students);
this.setState({
students,
isFetching: false,
});
})
)
.catch((error) => {
console.log(error.error.message);
// const message =error.error.message;
// errorNotification(message,message)
this.setState({
isFetching: false,
});
});
};
The problem is that I get is that "message" is undefined I want to log "Opps can not get all students" in the console:
Add this line to your application.properties file:
server.error.include-message=always
And try throwing ResponseStatusException, so that you give a HTTP Status, together with the message, and not just 500 Server Error.
Like this:
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Your Message...");
Error handling middleware in node js backend:
app.use((error, req, res, next) => {
console.log(error);
const status = error.statusCode || 500;
const message = error.message;
const data = error.data;
res.status(status).json({ message: message, data: data });
});
I have the following try catch block from my app:
userLogin() {
//axios vue instance
this.$http
.post("/auth/signup", this.formData)
.then((res) => {
// res.status == 201 ? (this.formData = {}) : "";
console.log(res);
})
.catch((err) => {
console.log(err);
console.log(err.data.data);
console.log(err.data.msg);
});
},
The output of the above catch block are as follows:
[![enter image description here][2]][2]
While my rest api sends the message in following format (seen on Network > Preview)
{
message: "Validation failed.",
…
}
data: [{
location: "body",
param: "email",
value: "test#test.com",
msg: "E-Mail address already exists!"
}]
message: "Validation failed."
I want to access the data array and print its content.
How can I access data ?
We can catch custom error message:
userLogin() {
this.$http
.post("/auth/signup", this.formData)
.then((res) => {
// res.status == 201 ? (this.formData = {}) : "";
console.log(res);
})
.catch((err) => {
console.log(err.response.data.data);
});
},
Axios stores the actual response in its data prop (unrelated to your API's data property in the response contents), so you could access your data property like this:
this.$http.post('/auth/signup', this.formData)
.then((res) => {
const apiResponse = res.data
console.log(apiResponse.data) // logs `data` property from API response contents
})
.catch((err) => {
/*...*/
})
More readable format
async userLogin() {
try {
// Call the server
const {data} = await this.$http.post("/auth/signup", this.formData);
// If you want message
let message = data.message;
// If you want the data object, ex data: [{location: "body"....}]
let dataObject = data.data;
} catch (e) {
// In case of error
console.log(err.response);
}
};
I'm trying to display data from my web using API. My API is working correctly. But some how i face this issue json.data is not a function. (In 'json.data()', 'json.data' is an instance of Array)]. Can I anyone help me on this?
_loadInitialState = async () => {
const token = await AsyncStorage.getItem('token');
const myArray = await AsyncStorage.getItem('language_type');
_onSetLanguage(myArray)
var loadAll = this.props.navigation.getParam('loadAll');
if (loadAll == true) { this.setState({ isLoading: true }) }
var have_access = this.props.navigation.getParam('have_access');
if (have_access != undefined) { this.setState({ have_access: have_access }) }
if (staticData.get_centre_settings() != null) { this.setState({ have_access: true }) }
let today = Moment();
this.setState({
today: Moment(today).format('YYYY-MM-DD'),
})
// alert(FetchURL.get_baseURL() + "leave?centre_id=" + staticData.get_centre_settings().centre.centre_id)
// alert(token)
// return
fetch(FetchURL.get_baseURL() + "leave?centre_id=" + staticData.get_centre_settings().centre.centre_id, {
method: 'GET',
headers: {
'Authorization': 'Bearer '+ token,
}
})
.then(response => response.json())
.then((json) => {
// alert(json)
if (json.error) {
alert(json.error);
} else {
this.setState({
staffLeave: json.data(),
isLoading: false
});
}
})
.catch((err) => {
console.log(err)
alert(err)
// alert(strings.data_fail);
})
this.setState({ view_access: true })
}
I kept searching for this but couldn't find an answer that will make this clear.
Thanks!
You have the response after response.json() as json. If you want to store it to state, use json.data and not json.data(), just as you check for json.error.
When you read the error json.data is not a function. (In 'json.data()', 'json.data' is an instance of Array)]
What this is telling you is that json.data is not a callable function. Therefore json.data() will not work. json.data is an array per the error message. You would access some part of that by: json.data[0] But you'd want to check the length of that array and understand the type (which Typescript helps solve).
// alert(json)
if (json.error) {
alert(json.error);
} else {
this.setState({
staffLeave: json.data(),
isLoading: false
});
}
Replace with
if (json.error) {
alert(json.error);
} else {
this.setState({
staffLeave: json.data,
isLoading: false
});
}
hopefully, it's work.