I am new to React so there might be a lot of mistakes around. Also, I know there are similar questions, but none helped with my problem so far.
I'm working on a project (using a template) that is using Java Spring (back-end) and ReactJS (front-end).
At the moment I am trying to make a login form, and verify the credentials.
These are the functions that I use when I press Login:
onSubmit(){
let login = {
username: this.state.username,
password: this.state.password
};
this.checkLogin(login);
}
checkLogin(login){
return this.sendRequest(login, (result, status) => {
console.log("AICI NU AJUNG CRED");
if (result !== null && (status === 200 || status === 201)) {
console.log("Successfully inserted person with id: " + result);
this.reloadHandler();
} else {
console.log("There was an error " + result);
}
});
}
sendRequest(login, callback){
let request = new Request(HOST.backend_api + endpoint.login + "/login", {
method: 'POST',
headers : {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(login)
});
console.log(request.url);
console.log(login);
RestApiClient.performRequest(request, callback);
}
function performRequest(request, callback){
fetch(request)
.then(
function(response) {
if (response.ok) {
response.json().then(json => callback(json, response.status,null));
}
else {
response.json().then(err => callback(null, response.status, err));
}
})
.catch(function (err) {
//catch any other unexpected error, and set custom code for error = 1
callback(null, 1, err)
});
}
I try it with a "test" username and "test" password I have in my database.
And this is the result:
dev console result 1
dev console result 2
Related
I'm trying to do a PUT request to an update controller from a react form (Mongoose API). Everything is passing over to the request, except the body. Now, this is my first time using FormData, so I'm almost positive that is where the issue lies, but I can't seem to sort out where the problem is..
The Submit action from the form
const clickSubmit = () => {
// console.log('Values on submit before FormData: ', values) // Shows the state object as expected
let userData = new FormData()
values.name && userData.append('name', values.name)
values.email && userData.append('email', values.email)
values.password && userData.append('password', values.password)
values.about && userData.append('about', values.about)
values.photo && userData.append('photo', values.photo)
update({
userId: match.params.userId
}, {
t: jwt.token
}, userData).then((data) => {
if (data && data.error) {
setValues({...values, error: data.error})
} else {
setValues({...values, 'redirectToProfile': true})
}
})
}
The Helper Method that set up the request
const update = async (params, credentials, user) => {
console.log('The params: ', params) // passes the user ID just fine
console.log('The credentials:', credentials) // passes the JWT just fine
console.log('The user object: ', ...user) // has all the information I'm updating, albeit in an array form that I can't really work with
try {
let response = await fetch('/api/users/' + params.userId, {
method: 'PUT',
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer ' + credentials.t
},
body: user
})
return await response.json()
} catch (err) {
console.log(err)
}
}
And the controller I've commented out the rest of the logic to remove the clutter while I TS this issue
const update = async (req, res) => {
console.log(req)
const user = await User.findById(req.params.userId)
console.log('user after find: ', user) // returns the user that I want to modify from the database
console.log('body of request: ', req.body) // empty object
}
UPDATE:
I was able to get the FormData into an actual object using Object.fromEntries(user) - but it still won't pass into the request.. I have tried two ways:
const update = async (params, credentials, user) => {
console.log('The params: ', params)
console.log('The credentials:', credentials)
console.log('The user object: ', ...user)
let infoToUpdate = Object.fromEntries(user)
console.log('infoToUpdate: ', infoToUpdate);
try {
let response = await fetch('/api/users/' + params.userId, {
method: 'PUT',
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer ' + credentials.t
},
body: {
"name": infoToUpdate.name,
"email": infoToUpdate.email,
"about": infoToUpdate.about
}
})
return await response.json()
} catch (err) {
console.log(err)
}
}
And
const update = async (params, credentials, user) => {
console.log('The params: ', params)
console.log('The credentials:', credentials)
console.log('The user object: ', ...user)
let infoToUpdate = Object.fromEntries(user)
console.log('infoToUpdate: ', infoToUpdate);
try {
let response = await fetch('/api/users/' + params.userId, {
method: 'PUT',
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer ' + credentials.t
},
body: infoToUpdate
})
return await response.json()
} catch (err) {
console.log(err)
}
}
But req.body is still an empty object..
This has been solved, and it was all my flippin computer's fault..
On a whim, I killed node_modules and the package.lock files and reinstalled the deps.. and it started working.. My guess is that bodyParser didn't fully install..
Thank you all for the help.
I try my best to make a Sign-in form with React native but :
I can't make a redirection to 'App', the error message is : (TypeError: undefined is not an object (evaluating 'this.props.navigation')])
try {
fetch('http://93.xxx.xx.xx:5151/login', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
},
body: formBody,
})
.then(function(response) {
if (response.ok) {
this.props.navigation.navigate('App');
} else {
throw new Error("Failed to fetch [error : " + response.status + "]");
Alert.alert("Error [" + response.status + "] - " + response.statusText);
}
})
.then(function(response) {
if (response.ok) {
Alert.alert(response.userToken);
console.log(response);
} else {
Alert.alert("Error [" + response.status + "] - " + response.statusText);
}
})
} catch (error) {
if (error) {
console.error(error);
}
}
Is anyone know how to do that ?
I only have one solution so far :
fetch('http://93.xxx.xx.xx:5151/login', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
},
body: formBody
})
.then(res => {
if (res.ok) {
this.props.navigation.navigate('App')
} else {
if (res.status == 400) {
Alert.alert("Error 400 : login rejected because -> " + res.message)
} else {
throw Error(`Request rejected with status ${res.status}`);
}
}
})
.catch(console.error)
}
But with this solution i don't know how to save the User token ...
Its a scoping issue , change this :
.then(function(response) { // due to this you are losing `this` scope inside it
// due to that, this is not accessible, in result you will get error
this.props.navigation.navigate('App');
To :
.then((response) => { // <--- Fat arrow is what you need
The first one is a scope issue. If you want to use "this" in an anonymous function, you need to bind it to your object.
There are two ways to do that:
1) If you use the old function style, the former object don't get automatically bound to it. Therefore you need to bind the parent object manually.
If you want a little more explanation about it, look here: What is the use of the JavaScript 'bind' method?
Promise.then(function(res) {
return "Your return"
}.bind(this));
2) The second way is to use the ES6 "Fat arrow"-Function. This works internally a bit different and binds the content of the parent Obejct directly.
Promise.then(res => "Your return");
On your second Problem I don't fully understand what your goal is. Do you want the user token in your next route? If so, you should use "setParams":
fetch('http://93.xxx.xx.xx:5151/login', {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'},
body: formBody
})
.then(res => {
if(res.ok) {
this.props.setParams({
token: res.userToken
})
this.props.navigation.navigate('App')
} else {
if (res.status == 400) {
Alert.alert("Error 400 : login rejected because -> " + res.message)
} else {
throw Error(`Request rejected with status ${res.status}`);
}
}})
.catch(console.error)
}}
I am working on simple user login in ReactJs with Nodejs and Express-session. I got problem that my front end (React login page) not working. here is the Fetch API that I used in Login.js:
SubmitLogin (event) {
event.PreventDefault();
debugger;
fetch('http://localhost:4000/login', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type' : 'application/json'
},
body : JSON.stringfy (this.state)
}).then((Response) => Response.json())
.then((result) => {
console.log(result);
if (result.Status === 'Invalid')
alert('Invalid User');
else
this.props.history.push({Home});
alert('Login Sucessfull');
})
console.log(this.state);
alert("test input login")
}
for connecting to backend, I added server.js with coded like this :
app.post('/login', jsonParser, (req, res) => {
var username = req.body.username;
var password = req.body.password;
if (username && password) {
dbConn.query(`SELECT * FROM user_tbl WHERE username = ? AND password = ?`, [username, password], (err, results, fields) => {
if (results.length > 0) {
req.session.loggedin = true;
req.session.username = username;
res.redirect('/home');
console.log(results)
} else {
res.send('Incorrect Username and/or Password!');
}
res.end();
});
} else {
res.send('Please enter Username and Password!');
res.end();
}
});
app.get('/home', (req, res) => {
if (req.session.loggedin) {
res.send('Welcome back, ' + req.session.username + '!');
} else {
res.send('Please login to view this page!');
}
res.end();
});
I already tested back end using postman, and it's working. Please help me with some suggestion and how I can put console.log to find the error in Login.js. Thanks for help
the result in postman :
Change the Response.json() to Response.text() as you are returning text in response not json, and you could add the catch block to handle the errors.
I can see in your code that you are using Content-Type application/x-www-form-urlencoded in the Postman and application/json in the fetch call. use same Content-Type in both request.
SubmitLogin(event) {
event.PreventDefault();
fetch('http://localhost:4000/login', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringfy(this.state)
}).then((Response) => Response.text())
.then((result) => {
console.log(result);
if (result.Status === 'Invalid')
alert('Invalid User');
else
this.props.history.push({ Home });
alert('Login Sucessfull');
}).catch(error => {
console.error(error)
})
console.log(this.state);
alert("test input login")
}
You could change your code to use async/await for better readability.
async SubmitLogin(event) {
event.PreventDefault();
try {
let response = await fetch('http://localhost:4000/login', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringfy(this.state)
});
let result = await response.text();
console.log(result);
if (result.Status === 'Invalid')
alert('Invalid User');
else
this.props.history.push({ Home });
alert('Login Sucessfull');
} catch (error) {
console.error(error.message);
}
console.log(this.state);
alert("test input login")
}
I want to use received data from server on client . I use a NodeJS Server with NextJS and React.
I use this function on the server:
function addEmailToMailChimp(email, callback) {
var options = {
method: 'POST',
url: 'https://XXX.api.mailchimp.com/3.0/lists/XXX/members',
headers:
{
'Postman-Token': 'XXX',
'Cache-Control': 'no-cache',
Authorization: 'Basic XXX',
'Content-Type': 'application/json'
},
body: { email_address: email, status: 'subscribed' },
json: true
};
request(options, callback);
}
The function will be run from this point:
server.post('/', (req, res) => {
addEmailToMailChimp(req.body.email, (error, response, body) => {
// This is the callback function which is passed to `addEmailToMailChimp`
try {
var respObj = {}; //Initial response object
if (response.statusCode === 200) {
respObj = { success: `Subscribed using ${req.body.email}!`, message: JSON.parse(response.body) };
} else {
respObj = { error: `Error trying to subscribe ${req.body.email}. Please try again.`, message: JSON.parse(response.body) };
}
res.send(respObj);
} catch (err) {
var respErrorObj = { error: 'There was an error with your request', message: err.message };
res.send(respErrorObj);
}
});
})
The try method is used to verify that an email address could be successfully saved to MailChimp. An appropriate message is sent to the client.
On the Client-Side, i use this function to receive and display the data from the server:
handleSubmit() {
const email = this.state.email;
this.setState({email: ""});
fetch('/', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({email:email}),
}).then(res => {
if(res.data.success) {
//If the response from MailChimp is good...
toaster.success('Subscribed!', res.data.success);
this.setState({ email: '' });
} else {
//Handle the bad MailChimp response...
toaster.warning('Unable to subscribe!', res.data.error);
}
}).catch(error => {
//This catch block returns an error if Node API returns an error
toaster.danger('Error. Please try again later.', error.message);
});
}
The problem: The email address is saved successfully at MailChimp, but the message is always displayed: 'Error. Please try again later.'from the .catch area. When i log the error from the catch area i get this:
TypeError: Cannot read property 'success' of undefined
Where is my mistake? I have little experience in Node.js environments. I would be very grateful if you could show me concrete solutions. Thank you for your replies.
With fetch theres no data property on the response. You have to call res.json() and return that promise. From there the response body will be read and deserialized.
handleSubmit() {
const email = this.state.email;
this.setState({email: ""});
fetch('/', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({email:email}),
})
.then(res => {
console.log(res); //to make sure the expected object is returned
if(res.data.success) {
//If the response from MailChimp is good...
toaster.success('Subscribed!', res.data.success);
this.setState({ email: '' });
} else {
//Handle the bad MailChimp response...
toaster.warning('Unable to subscribe!', res.data.error);
}
}).catch(error => {
//This catch block returns an error if Node API returns an error
toaster.danger('Error. Please try again later.', error.message);
});
}
Two things you need to change:
Call and wait for res.json() to get the response body as json object.
The result of 1. is your 'data' object that you can use directly
handleSubmit() {
//...
fetch('/', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({email:email}),
})
.then(res => res.json())
.then(data => {
if(data.success) {
//...
toaster.success('Subscribed!', data.success);
} else {
toaster.warning('Unable to subscribe!', data.error);
}
}).catch(error => {
//...
});
}
So basically I am sending data with a fetch POST or PATCH method and when I have an error I can see in the network -> response this error:
{
"Errors": [
{
"Code": -201,
"Message": "Could not get file from link",
"AssociatedError": "404 Not Found"
}
],
"Result": null
}
Here is my actual code:
function checkStatus(response) {
if (response.status >= 200 && response.status < 300) {
return response;
} else {
var error = new Error(response.statusText);
error.response = response;
throw error;
}
}
export function sendImageUploaded(data, valueMethod, endpoint) {
return dispatch => {
dispatch(requestPosts(data));
return fetch(endpoint, {
method: valueMethod,
headers: new Headers({
Authorization: Isengard.config.token
}),
body: data
})
.then(checkStatus)
.then(reponse => {
dispatch(successSent("The output list has been successfully sent!"));
}).catch(err => {
console.log('request failed', err);
dispatch(failSent("Error on sending request: " + err));
});
};
};
And I am struggling on having this error message.
You already got your response error in "error.response". You only have to resolve that promise.
instead of
.catch(err => {
console.log('request failed', err);
dispatch(failSent("Error on sending request: " + err));
});
use
.catch(err => {
err.response.json().then((json) =>{
let {Errors,Result} = json;
dispatch(failSent(Errors)); // You are sending your array of errors here
});
});