React using fetch to get token and checking response status? - javascript

I'm trying to check the status of a login via REST call and JWT token so that if that status is not ok then it'll return false, but this is what I'm getting.
export function login(data){
fetch('http://localhost:8000/token-auth/', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(data)
}).then(res => res.json())
.then(json =>
console.log(json.token) <= This prints correctly
)
}
I tried adding in a check in this function, but then I no longer get the the token printed out
export function login(data){
fetch('http://localhost:8000/token-auth/', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(data)
}).then(res => {
if(res.ok){
console.log(res.json()) <= This prints something about promise
console.log(res.json().token) <= this prints 'undefined'
}
}).then(json =>
console.log(json.token) <= This prints 'undefined'
)
}

Can you use a catch block instead? Like so:
export function login(data){
fetch('http://localhost:8000/token-auth/', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(data)
}).then(res => res.json())
.then(json =>
console.log(json.token)
).catch(error =>
console.log(error.response)
)
}

Related

Passing a value from one request to another request in ReactJs

I need help because I couldn't use a separate function to generate the token - it gives out a promise, not a value. I was told that a value can only be used inside a function.
For each request, I generate a new token in the first request and then pass that token into the second request.
I tried making a separate function to generate the token, but fetch returns a promise.
As a result, I made such a big function and it works.
Is there a way to make a separate function for the first request and pass the result to the second request?
The first token generation function is required frequently, while the second request is always different.
fetch('/api/token', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ 'id': '5' }),
})
.then(response => response.json())
.then(result => {
fetch('/api/reviews', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + result.token,
},
body: JSON.stringify({ 'limit': 10 }),
})
.then(response => response.json())
.then(result => {
this.setState({ data: result.data });
})
})
create a function that return promise
async function getToken() {
return await fetch('/api/token', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ 'id': '5' }),
})
.then(response => response.json())
.then(result => {
return Promise.resolve(result.token);
}).catch(error => {
return Promise.reject(error);
})
}
async function getReview() {
const token = await getToken().then(token => {
return token
}).catch(error => {
//handle error
});
fetch('/api/reviews', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token,
},
body: JSON.stringify({ 'limit': 10 }),
})
.then(response => response.json())
.then(result => {
this.setState({ data: result.data });
})
}
i did not test this code but you get the idea
i will test and update my answer asap
Yes you can with async / await. It will allow you to lift the lexical scope of the API response from inside the .then "callback hell" and into the parent function scope.
Your separate function which fetches the token will return a promise, but then the requesting function will wait for the promise to execute and resolve before continuing.
async function fetchToken() {
const response = await fetch('/api/token', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ 'id': '5' }),
})
return await response.json();
}
async function getReviews() {
const response = await fetch('/api/reviews', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + result.token,
},
body: JSON.stringify({ 'limit': 10 }),
})
const result = await response.json();
this.setState({ data: result.data });
}
Additionally, if the token call does not need to be made every time the reviews call is made, then you can memoize the value, and use that memoized value.
const tokenMemo = useMemo(async () => await getToken(), []);
async function getReviews() {
const response = await fetch('/api/reviews', {
// ...
'Authorization': 'Bearer ' + tokenMemo,
// ...
}

Having a problem properly getting information from canvas and sending information to discord through webhook with node-fetch

So I am trying to send data from canvas's api using a GET and use that information and send a POST from the same endpoint to discord using node fetch. I can receive data from canvas without issue and I console log to make sure I have to right data, but I can't seem to get any information to discord. I am using discords webhooks and I can't figure out where I am going wrong.
fetch(url + `courses/${course}/discussion_topics` , {
method: "GET",
headers : {
'Authorization' : 'Bearer <auth token>',
'Content-Type' : 'application/json'
}
})
.then(res => res.json())
.then(data => {
console.log(data[0].id);
console.log(data[0].title);
console.log(data[0].message);
}
)
.then(fetch("https://discord.com/api/webhooks/893327519103746149/<webhooktoken>", {
method: "post",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: {content: 'hello world'}
}))
.catch(err => console.log(err))
});```
As mentioned in the comment, just in case you have some typo or misunderstanding.
Also, you need to JSON.stringyify your body.
Please try the example below:
fetch(url + `courses/${course}/discussion_topics`, {
method: "GET",
headers: {
Authorization: "Bearer <auth token>",
"Content-Type": "application/json",
},
})
.then(res => res.json())
.then(data => {
console.log(data[0].id);
console.log(data[0].title);
console.log(data[0].message);
})
.then(() =>
fetch(
"https://discord.com/api/webhooks/893327519103746149/<webhooktoken>",
{
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
username: "Canvas-Bot",
content: "hello world",
}),
}
)
.then(res => res.json())
.then(data => {
console.log({ data });
})
)
.catch(err => console.log(err));
Another approach would be in async/await. I think it is cleaner.
(async function main() {
try {
const res1 = await fetch(url + `courses/${course}/discussion_topics`, {
method: "GET",
headers: {
Authorization: "Bearer <auth token>",
"Content-Type": "application/json",
},
});
const data1 = await res1.json();
console.log(data1);
const res2 = await fetch(
"https://discord.com/api/webhooks/893327519103746149/<webhooktoken>",
{
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
username: "Canvas-Bot",
content: "hello world",
}),
}
);
const data2 = await res2.json();
console.log(data2);
} catch (err) {
console.log(err);
}
})();

How to fixed this error -> Uncaught (in promise) SyntaxError: Unexpected end of input In Fetch Api

I am calling this function on button click.
I have added a header in my API still it shows an error.
let getData = () => {
console.log("getData function started");
const options = {
method: "GET",
headers: new Headers({ 'content-type': 'application/json' }),
mode: 'no-cors'
};
fetch("http://167.71.226.242/", options).then((response) => {
console.log("Inside 1st then");
return response.json();
}).then((data) => {
console.log("Inside 2nd then");
console.log(data);
});
}
var requestOptions = {
'content-type': 'application/json',
method: 'GET',
redirect: 'follow'
};
fetch("http://167.71.226.242", requestOptions)
.then(response => response.json())
.then(data => console.log(data));
This code work. you don't use new Header(...) in options!
Read more about fetch()
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#supplying_request_options
It's possible you'll just want to do this and also use the correct header name as yours is lowercase:
fetch('/', {
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
}).then(...);
It doesn't look like you need to use new Headers(); as well.
You may also not need mode: 'no-cors' but that's your call :)

making two fetch requests in one function with a delay in between

so I have 2 endpoints, I'm making a "post" request to the first one and in the response I should get some kind of id that I use in the second request endpoint url. so I want to make a delay or something till I get the response from the first request.
req = () => {
fetch('url', {
method: 'POST',
headers: {
'Authorization': bearer,
'Content-Type': 'application/json',
},
body:
})
.then(response => response.json())
.then(json => {
})
fetch(`url with the id I get from the first request`, {
method: 'GET',
headers: {
'Authorization': bearer,
'Content-Type': 'application/json',
}
})
.then(response => response.json())
.then(json => {
})
}
There is no need for a delay per se. You can place your second request in the .then of the first request. This will ensure that your second request will run only once the first one has resolved. Another important note here, is that if you need a value of the first response in order to make the second request, you can only do that in the .then of the first request because otherwise the value you need to make the second request will be out of scope. Here is your code with the required modification.
req = () => {
fetch('url', {
method: 'POST',
headers: {
'Authorization': bearer,
'Content-Type': 'application/json',
},
body:
})
.then(response => response.json())
.then(json => {
fetch(`url with json.id or whatever`, {
method: 'GET',
headers: {
'Authorization': bearer,
'Content-Type': 'application/json',
}
})
.then(response => response.json())
.then(json => {
})
})
}
You can chain your second fetch request in your first request as:
req = () => {
fetch("url", {
method: "POST",
headers: {
Authorization: bearer,
"Content-Type": "application/json"
}
body:
})
.then(response => response.json())
.then(json => {
fetch("url with the id I get from the first request", {
method: "GET",
headers: {
Authorization: bearer,
"Content-Type": "application/json"
}
})
.then(response => response.json())
.then(json => {});
});
};
Or you can use async/await.
req = async () => {
const first = await ( await fetch( "url", {
method: "POST",
headers: {
Authorization: bearer,
"Content-Type": "application/json",
},
body:
} ) ).json();
const second = await ( await fetch( `http://some.url${ first.id }` ),
{
method: "GET",
headers: {
Authorization: bearer,
"Content-Type": "application/json",
},
} ).json();
// use the variable second as your last result here.
};

Return variable with React method

I have this function in JS:
export let findUser = (user, pass) => fetch(baseURL+'/api/Login',{
method: 'POST',
headers:{
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
username:user,
password:pass,
})
})
.then((response) => response.json())
.then((res) => {
if(res.success === true){
return 'A';
}else{
alert(res.message);
}
}).
.done();
But when I call it in React like this :
var user = file.findUser(this.state.username,this.state.password);
I got undefined as content of variable user, How can I pass a value from the first function and get it in react native ?
I would suggest exporting the initial method call and handling the .then() and .done() within the area being exported to. For example:
I have this function in JS:
export let findUser = (user, pass) => fetch(baseURL+'/api/Login',{
method: 'POST',
headers:{
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
username:user,
password:pass,
})
})
using in another file
let user // assign user within response block
file.findUser(this.state.username, this.state.password)
.then((res) => { /* do what you want */ })
.then((res) => { /* do what you want */ })
.done()

Categories