How to store asynchronous data inside a variable Fetch API - javascript

I am working on a project that uses Laravel for back-end and React for front-end.
Whenever the user clicks login, a modal will open that will, up on submitting, fetch the users bearer token.
These fetch functions are all located inside AuthService.js
export function getLoginToken(email, password) {
fetch("/api/login", {
method: "post",
credentials: 'include',
headers: {
'Accept': 'application/json',
"Content-type": "application/json",
},
body: JSON.stringify({
'email': email,
'password': password
})
}).then((response) => response.json())
.then((responseJSON) => {
return responseJSON;
})
}
The Nav component is where the login button resides, so I'm importing and using the funcionts that I've created inside AuthService.js
When I console log the json result within the actual getLoginToken function, there is no problem. Because up on placing it inside .then() it waits for it to complete so it doesn't result in undefined.
Now.. Inside the Nav component, there is an onClick function bound to the login button, which will execute AuthService.getLoginToken(email, password)
Actual problem:
I would like to store the response data inside a variable, but i keep getting undefined. This because I'm trying to insert asynchronous data inside a synchronous function.
I've also tried:
AuthService.getLoginToken(loginEmail, loginPassword).then((result) => {
this.setState({
token: result
});
});
But this will also return: Cannot read property 'then' of undefined.
Any ideas on how to fix this?

Try this
export function getLoginToken(email, password) {
return fetch("/api/login", {
method: "post",
credentials: 'include',
headers: {
'Accept': 'application/json',
"Content-type": "application/json",
},
body: JSON.stringify({
'email': email,
'password': password
})
}).then((response) => response.json())
.then((responseJSON) => {
return responseJSON;
})
}
Proper way would be to use state management tool like redux

You can use async await. Or use redux-thunk if you are doing redux.

Related

How to get the response object of an ajax request with laravel?

Guys I'm making a fetch request for laravel without using jquery and I would like to get the return of this request, however when I give a console.log() in the response the console informs undefined.
This is my request:
fetch(action, {
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
"X-Requested-With": "XMLHttpRequest",
"X-CSRF-Token": token
},
method: "post",
credentials: "same-origin",
body: JSON.stringify({
email: email,
password: password
})
})
.then(response => response.json())
.then(data => console.log(data))
.catch(err => console.log(err))
This is my controller that returns the empty field information:
public function login(Request $request)
{
if (in_array('', $request->only('email', 'password'))) {
$json['message'] = "Empty";
return response()->json($json);
}
var_dump($request->all());
}
The request was successful and the browser informs the response message:
Object response message
However console.log(data) returns undefined, how can I return the object that contains the message?
Taking advantage of the question, is this the best way to make this request?
Thank you guys

How to get a value from a promise to global scope in reactjs?

I am working on user authentication using web tokens in react. I am using fetch() to make a POST request to my backend using CORS. Trying to use setToken() hook inside the .then() gives an error. I tried storing the token to another variable, and using setToken() outside the promise, but to no avail. Here's the code:
const [ token, setToken ] = useState('')
// Configuration for POST fetch method
const url = 'http://localhost:8080/users/login'
const requestOptions = {
method: 'POST',
headers: { 'Content-type': 'application/json' },
body: JSON.stringify(userData)
}
let tempToken = ''
fetch(url, requestOptions)
.then(res => res.json())
.then(data => {
tempToken = data.token
// console.log(tempToken) // DEBUG
})
.catch(e => console.log(e))
setToken(tempToken)
// console.log(token) // This logs default value of token, which is ''
This is all inside a function. What is going wrong here? Also is there another way to do this, much appreciated. Thanks.
What is my problem: Cannot extract token from promise.
P.S: Also, on a completely different note, I tried using async await but it gave a response (shown below), where I couldn't even find the body of the json. Hence using .then()
Response {type: "cors", url: "http://localhost:8080/users/login", redirected: false, status: 200, ok: true, …}
body: (...)
bodyUsed: false
headers: Headers {}
ok: true
redirected: false
status: 200
statusText: "OK"
type: "cors"
url: "http://localhost:8080/users/login"
__proto__: Response
Fetch returns a promise, you need wait to get the token and then use setToken. Moreover you're calling fetch directly and updating the state even before rendering, that might leads to warnings/side effects. You can use useEffect hook to call api and update the state
useEffect(() => {
const url = 'http://localhost:8080/users/login'
const requestOptions = {
method: 'POST',
headers: { 'Content-type': 'application/json' },
body: JSON.stringify(userData)
}
fetch(url, requestOptions)
.then(res => res.json())
.then(data => {
setToken(data.token)
})
.catch(e => console.log(e))
}, [])

How to return a response from a fetch in javascript

I am having trouble returning the response for a API call in my React Native project.
let response = fetch('http://3.133.123.120:8000/auth/token', {
method: "POST",
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
client_id: 'NTMtzF7gzZPU9Ka35UFsDHvpR8e4D1Fy4OPRsurx',
grant_type: 'password',
username: user,
password: pass,
})
})
.then((response) => response.json())
.then((response) => this.setState({jsonData: response}))
.then(() => alert('resposne jsonData: ' + JSON.stringify(this.state)));
alert('resposne jsonData: ' + JSON.stringify(response))
The code above returns the correct response in the bottom .then() statement, however, I have not been able to use the data outside of the fetch() statement.
Anything I've tried to use outside of the fetch() (like my alert in bottom line) has given me the following...
{"_40":0,"_65":0,_55":null,"_72":null}
Please also note this is all inside a React class Component
fetch returns a Promise: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
You already have access to the value in that final then. If you're looking for a way to use the value below without using a callback, you could consider async/await style and wrapping this code in a function like so:
const fetchData = async () => {
const results = await fetch() // put your fetch here
alert(results.json());
};
fetch info:
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
async/await info:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await

Adding a user using fetch with POST method

Using the following code, I'm trying to add a new user and console log all users including the new added one:
const url = "https://jsonplaceholder.typicode.com/users";
// Creating a user
fetch(url, {
method: "POST",
body: JSON.stringify({
name: "Robert Miller",
username: "robby",
email: "roby#outlook.com"
}),
headers: {
Accept: "application/json, text/plain, */*",
"Content-Type": "application/json"
}
})
.then(response => response.json())
.then(response => console.log(response));
However, the console.log shows only the added user but not all users.
My assumption was that because the method of the fetch is POST, I need to send another request via GET to get all users and came up with this:
const url = "https://jsonplaceholder.typicode.com/users";
// Creating a user
fetch(url, {
method: "POST",
body: JSON.stringify({
name: "Robert Miller",
username: "robby",
email: "roby#outlook.com"
}),
headers: {
Accept: "application/json, text/plain, */*",
"Content-Type": "application/json"
}
})
.then(response => response.json())
.then(response => console.log(response));
fetchAllUsers();
function fetchAllUsers() {
fetch(url)
.then(response => {
if (!response.ok) {
throw Error(response.statusText);
}
// Read the response as json.
return response.json();
})
.then(data => {
// Do stuff with the JSON
console.log(data);
})
.catch(error => {
console.log("Looks like there was a problem: \n", error);
});
}
But I still cannot see the added user in the list. Any help?
I think this link is answer your question:
Unable to post a new user
Since JSONPlaceholder is a shared API used by many, modifications are faked (POST, PUT, PATCH) and resources are read-only. This is to avoid user "A" creating new resources and having user "B" impacted by them.
If you need to make changes and persist them between calls, you can run JSON Server locally.

React JS how to pass values between pages using session storage

I have a react JS login page that accepts the user name and password. Upon entering the user name and and password, the credentials are processed against a json (API) file, which generates a token for the client. My goal is to pass the token to a landing page after the client has logged in and populate a dropdown list with the clients respective data. The problem I am facing is getting the clients token to pass from my login page to the landing page.
In my login page, I am using Fetch to retrieve the token from the API and then store the token using session-storage. The code snippet for getting the token:
componentDidMount() {
this.fetchData();
}
//request the token
fetchData() {
return fetch('http://myapiaut:1111/api/auth', {
method: 'POST',
headers: {
'Content-type': 'application/json',
},
body: JSON.stringify({
username: 'myAdminusername',
password: 'myAdminPassword',
Authorization: 'myAdminPassword',
})
}) /*end fetch */
.then(results => results.json())
.then(data => {
this.setState({ data: data })
sessionStorage.setItem("token", data)
})
}
//authenticate request
requestUserInfo() {
var token = sessionStorage.getItem("token");
return fetch('http://myapiaut:1111/api/auth', {
method: 'GET',
headers: new Headers({
Authorization: 'Bearer' + sessionStorage.token
}),
})
.then((response) => response.json());
}
Landing page
componentDidMount() {
fetch('http://myapiclients:22222/api/clients', {
method: 'GET',
headers: {
'Content-type': 'application/json',
'Authorization': 'Bearer ' + sessionStorage.token
},
})
.then(results => results.json())
.then(data => this.setState({ data: data }))
}
...going back to the login page, I confirmed that I'm getting the token via fetchData function, but the problem I am encountering is properly storing the token so that it may be passed to the landing page.
FYI- I've already built the landing page and it functions properly when I manually copy the generated token into the Authorization section of the Fetch.
...Could, I please get some help as to what I'm doing wrong?
The problem is here:
.then(data => this.setState({ data: data }))
.then(data => sessionStorage.setItem('token', data))
setState doesn't resolve a Promise so it does not have then()
Change it to something like:
.then(data => {
this.setState({ data: data })
sessionStorage.setItem('token', data)
})
In landing page:
componentDidMount() {
fetch('http://myapiclients/api/clients', {
method: 'GET',
headers: {
'Content-type': 'application/json',
'Authorization': 'Bearer ${token}' // token is not defined!
},
})
.then(results => results.json())
.then(data => this.setState({ data: data }))
}
token is not defined, so it will be 'Bearer undefined', either define it before fetch(...) with sessionStorage.getItem("token") or in fetch headers do something like:
'Authorization': 'Bearer ' + sessionStorage.token

Categories