Cookies not being set immediately in react - javascript

I am using djangorestauth for the backend and the token it returns back is not saved in the cookies from universal cookies immediately. I have this handle login:
const handleLogin = (e) => {
e.preventDefault();
setIsClicked(true);
const csrftoken = getCookie("csrf");
const url = "http://localhost:8000/rest-auth/login/";
const cookies = new Cookies();
fetch(url, {
method: "POST",
headers: {
"Content-type": "application/json",
"X-CSRFToken": csrftoken,
},
body: JSON.stringify({
username: username,
password: password,
}),
})
.then((response) => response.json())
.then((key) => setToken(key.key));
cookies.set("token", token);
};
and a useEffect() to test
useEffect(() => {
if (isClicked) {
const cookies = new Cookies();
console.log("THE TOKEN COOKIE: ", cookies.get("token"));
setIsClicked(false);
}
}, [isClicked]);
The problem: When I click the Login button, the token returned was obviously not set immediately because it returns undefined or blank at the first click. And when I input the wrong username and password, the token is still being output

const handleLogin = (e) => {
e.preventDefault();
const csrftoken = getCookie("csrf");
const url = "http://localhost:8000/rest-auth/login/";
const cookies = new Cookies();
fetch(url, {
method: "POST",
headers: {
"Content-type": "application/json",
"X-CSRFToken": csrftoken,
},
body: JSON.stringify({
username: username,
password: password,
}),
})
.then((response) => response.json())
.then((key) => {
setToken(key.key)
cookies.set("token", key.key);
setIsClicked(true);
})
};
explanation
you need to await to finish the fetch
NOTE: setIsClicked change the name to isSubmitSuccess

Related

How do I declare the body of a POST with the fetch API

I am building a comments section onto a Node/Express app for family reunions. I first wrote it all on the server side, but then ran into the issue where I was unable to update the DOM after posting the comment without refreshing the page.
My research yielded that I could use AJAX or the fetch API to do this, client-side.
I'm using some client-side JavaScript to post comments. I have a route for the POST request:
router.post('/:reunionId', isAuth, reunionController.postComment);
The controller code is:
exports.postComment = (req, res, next) => {
const commentText = req.body.newComment;
const reunionId = req.body.reunionId;
const foundReunion = Reunion.findById(reunionId)
.populate({
path: 'comments',
options: { sort: { createdAt: -1 } },
})
.then((reunion) => {
console.log(reunion);
const comment = new Comment({
_id: new mongoose.Types.ObjectId(),
text: commentText,
reunionId: new mongoose.Types.ObjectId(reunionId),
userId: req.user._id,
});
foundReunion.comments.push(comment);
comment.save();
foundReunion.save();
console.log('Operation completed successfully');
return foundReunion;
})
.catch((error) => {
const newError = new Error(error);
newError.httpStatusCode = 500;
return next(newError);
});
};
And the client-side code:
const commentForm = document.getElementById('comment-form');
const commentInput = document.getElementById('newComment');
const commentsContainer = document.getElementById('allComments');
let commentText = document.getElementById('newComment').value;
const reunionId = document.getElementById('reunionId').value;
const csrfToken = document.getElementById('csrf').value;
commentForm.addEventListener('submit', handleCommentSubmit, false);
commentInput.addEventListener('change', (event) => {
commentText = event.target.value;
});
async function handleCommentSubmit(event) {
event.preventDefault();
console.log('Someone clicked the comment submit button...');
console.log(csrfToken); // This works.
console.log(reunionId); // This works.
console.log(commentText); // This works.
const url = `http://localhost:3006/reunions/${reunionId}`;
fetch(url, {
method: 'POST',
credentials: 'include',
headers: {
'X-CSRF-Token': csrfToken,
},
body: { // This is not working.
reunionId,
commentText,
},
})
.then((response) => {
const d = response.comment.createdAt.getDate();
const m = monthNames[response.comment.createdAt.getMonth()];
const y = response.comment.createdAt.getFullYear();
const commentDiv = document.createElement('div');
commentDiv.classList.add('comments-container');
const commentP = doucment.createElement('p');
commentP.classList.add('comment-header-text');
const email = response.comment.userId.email;
const hr = document.createElement('hr');
commentP.textContent = `On ${m}+ ' ' +${d}+ ', ' +${y}, ${email} wrote:`;
commentDiv.appendChild(commentP);
commentDiv.appendChild(commentText);
commentDiv.appendChild(hr);
commentsContainer.appendChild(commentDiv);
})
.catch((error) => console.log(error));
The client makes the POST request, properly passes the csrf token, but the server cannot read the reunionId or commentText from the body of the request. I get Reunion.findOne({ null }) in the server logs.
I am simply not sure what Content-Type to declare, whether I need to at all, or how to pass the two pieces of data I need in the body of the call to fetch.
Thanks very much in advance.
The body of a post must always be a string. What you are missing is you need to JSON.strigify your object and them make add the content-type header to specify that the body is application/json:
fetch(url, {
method: 'POST',
credentials: 'include',
headers: {
'X-CSRF-Token': csrfToken,
'Content-Type': 'application/json'
},
body: JSON.stringify({
reunionId,
commentText,
}),
})

How to make a fetch request to TinyURL?

I am trying to make a fetch request specifically a post request to tinyURL to shortern a url generated on my site. here is the tinyURL API
Currently, I am writing my code like this but it doesn't appear to be returning the short url.
the word tinyurl seems to be banned within links so all links
containing the word tinyurl have been replaced with "SHORT"
here is the tinyURL API https://SHORT.com/app/dev
import * as React from 'react'
interface tinyURlProps { url: string } export const useTinyURL = ({ url }: tinyURlProps) => { React.useEffect(() => {
const apiURL = 'https://api.SHORT.com/create'
const data = JSON.stringify({ url: url, domain: 'tiny.one' })
const options = {
method: 'POST',
body: data,
headers: {
Authorization:
'Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
Accept: 'application/json',
'Content-Type': 'application/json',
},
} as RequestInit
fetch(apiURL, options)
.then((response) => console.log(response))
.then((error) => console.error(error))
console.log('TinyUrl ran') }, [url])
}
The snippet below seems to work
const qs = selector => document.querySelector(selector);
let body = {
url: `https://stackoverflow.com/questions/66991259/how-to-make-a-fetch-request-to-tinyurl`,
domain: `tiny.one`
}
fetch(`https://api.tinyurl.com/create`, {
method: `POST`,
headers: {
accept: `application/json`,
authorization: `Bearer 2nLQGpsuegHP8l8J0Uq1TsVkCzP3un3T23uQ5YovVf5lvvGOucGmFOYRVj6L`,
'content-type': `application/json`,
},
body: JSON.stringify(body)
})
.then(response => {
if (response.status != 200) throw `There was a problem with the fetch operation. Status Code: ${response.status}`;
return response.json()
})
.then(data => {
qs(`#output>pre`).innerText = JSON.stringify(data, null, 3);
qs(`#link`).href = data.data.tiny_url;
qs(`#link`).innerText = data.data.tiny_url;
})
.catch(error => console.error(error));
body {
font-family: calibri;
}
<p><a id="link" /></p>
<span id="output"><pre/></span>

my post request get response as https but does not return to a new page (javascript)

I'm send a post request and I get the response like this
" [Symbol(Response internals)]: {
url: 'https://login.somenewloginpage'}"
and what I want to do is I want to open a new page via that url but it does not direct to the new page.
const login= () => async () => {
const api = `somePostRequest`
fetch(api, {
method: 'post',
headers: {
'Content-Type': 'application/x-www-form-url-encoded',
Accept: 'application/json',
},
})
.then(function(res) {
return res //maybe I should do something in this part...
})
.then(data => console.log(data));
};
Here's how to use fetch() with async/await syntax :
const login= () => async () => {
const api = `somePostRequest`;
const response = await fetch(api, {
method: 'post',
headers: {
'Content-Type': 'application/x-www-form-url-encoded',
Accept: 'application/json',
},
});
const data = await response.json(); // { url: 'https://login.somenewloginpage'}
window.location.replace(data.url); // <-- Redirection
};

Fetch with Post method in React-Native

I'm trying to do a fetch with the post method in my react-native, but I receive always an error:
TypeError: Network request failed
at XMLHttpRequest.xhr.onerror (whatwg-fetch.js:504)
at XMLHttpRequest.dispatchEvent (event-target.js:172)
at XMLHttpRequest.setReadyState (XMLHttpRequest.js:580)
at XMLHttpRequest.__didCompleteResponse (XMLHttpRequest.js:394)
at XMLHttpRequest.js:507
at RCTDeviceEventEmitter.emit (EventEmitter.js:181)
at MessageQueue.__callFunction (MessageQueue.js:366)
at MessageQueue.js:106
at MessageQueue.__guard (MessageQueue.js:314)
at MessageQueue.callFunctionReturnFlushedQueue (MessageQueue.js:105)
User creationg page
static createUser(Identity, FirstName, LastName, FiscalCode , Email) {
let formdata = new FormData();
formdata.append('Identity', JSON.stringify(Identity));
formdata.append('FirstName', (FirstName));
formdata.append('LastName', LastName);
formdata.append('FiscalCode', FiscalCode);
formdata.append('Email', Email);
return new Promise((resolve, reject)=> {
fetch('https://linktomyapi.com' , {
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
},
body: formdata
})
.then((response) => response.json())
.then((responseData) => {
if(responseData.Error){
Alert.alert("Errore");
}
global.utente = responseData;
resolve(responseData)
})
.catch((err) => {reject(err)})
})
}
About Identity, I take in this way:
let Identity =
{
AppName:
{
Username: this.state.FiscalCode,
Password: this.state.Password
}
}
I follow many guides about this argoument, but I don't understand why I receive these errors.
Can you try the following?
let params = {
Identity: JSON.stringify(Identity),
FirstName: FirstName,
LastName: LastName,
FiscalCode: FiscalCode,
Email: Email
}
return new Promise((resolve, reject)=> {
fetch('https://linktomyapi.com' , {
method: 'POST',
headers: {
"Content-Type": "application/json",
},
...(params && { body: JSON.stringify(params) })
})
.then((response) => response.json())
.then((responseData) => {
if(responseData.Error){
Alert.alert("Errore");
}
global.utente = responseData;
resolve(responseData)
})
.catch((err) => {reject(err)})
})
Are sure your content type is formdata?
The problem is there:
return new Promise((resolve, reject)=> {
fetch('https://linktomyapi.com' , {
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
},
body: formdata
})
In the fetch I pass the link as a string.
So the correct form is:
return new Promise((resolve, reject)=> {
fetch(https://linktomyapi.com , {
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
},
body: formdata
})

Server cookies lost on page refresh

I tried fetch to call api and passing credentials "include" to header which set cookies from server initially but on page refresh cookies got lost.
public post = async (payload:any, endpoint: string):Promise<any> => {
return new Promise((resolve, reject) => {
console.log(${config.baseUrl}${endpoint})
const URL = ${config.baseUrl}${endpoint};
fetch(URL, {
credentials: 'include',
method: 'POST',
body: JSON.stringify(payload),
headers: new Headers({
'Content-Type': 'application/json'
})
})
.then(data => data.json())
.then((data:any) => {
console.log("data", data)
const responsePayload = {
statusCode: data.status,
data: data
};
resolve(responsePayload);
})
.catch((error:any) => {
if (error.response === undefined) {
const errorpayload = {
statusCode: 503,
title: 'network error occured',
parameter: 'Network Error',
};
reject(errorpayload);
} else {
const errors = error.response.data.errors;
const errorPayload = {
statusCode: error.response.status,
data: error.response.data.errors,
};
reject(errorPayload);
}
});
});
};
Better read cookies on login and store it to loaclstorage and from there you can use it the way you want.

Categories

Resources