React Router Adds URL Query Params on POST Request - javascript

Hello my fellow nerds,
I am running into an issue where when I make a POST request (using Axios library inside of React function), it automatically appends all of the data from the "Create a User" form into search parameters in the URL of the page upon submission. I don't like this because I'd rather this stay hidden within the POST request, not flung out onto the page URL.
Image: URL after user was created
This is a direct result of React Router adding the data sent in the request of the body being appended to the location.search of react router's history object. So, naturally, since the react router history object is mutable, I tried adding this to the response of the submission:
this.props.location.search.replace({*some random parameter stuff here*});
This was in hopes it would remove all of that stuff from the URL and redirect to the page without search parameters. Anyways, I have seen a few other posts similar in nature but they don't seem to answer this exact question.
TL;DR: I am trying to send a POST request without React Router adding my req.body data to the params in my URL and the location.search object.
MY CODE:
Users.js: (front end)
handleSubmit (e) {
Axios.post(`${server}/s/admin/users/create`, {
headers: {
'Content-Type': 'application/json'
},
data: {
firstName: this.state.firstName,
lastName: this.state.lastName,
username: this.state.username,
password: this.state.password,
email: this.state.email
}
}).then((res) => {
console.log(res);
}).catch(err => console.log(err));
}
users.js: (back end)
app.post("/s/admin/users/create", (req, res) => {
let rb = req.body.data;
let newUser = new User({
_id: uid.time(),
orgID: req.session.orgID,
email: rb.email,
username: rb.username,
password: bcrypt.hashSync(rb.password, hashRate),
firstName: rb.firstName,
lastName: rb.lastName,
data: { exist: "true" },
settings: { exist: "true" }
});
// Save new owner to db
newUser.save((err, data) => {
if (err) return console.error(err);
res.json({info: `A new user, ${newUser.firstName} ${newUser.lastName}, has been created successfully.`});
});
});
Thank you!
P.S. This is my first post, thank you for your patience. I've tried searching and solving this issue for about a day now.

Can you try rewriting it this way? cause axios.post expect
axios({
method: 'post',
url: `${server}/s/admin/users/create`,
headers: {
'Content-Type': 'application/json'
},
data: {
firstName: this.state.firstName,
lastName: this.state.lastName,
username: this.state.username,
password: this.state.password,
email: this.state.email
}
}).then((res) => {
console.log(res);
}).catch(err => console.log(err));
Axios.post method expect the second argument as data but you have passed config, another way is to pass data and config in the third argument.
handleSubmit(e) {
Axios.post(`${server}/s/admin/users/create`, {
firstName: this.state.firstName,
lastName: this.state.lastName,
username: this.state.username,
password: this.state.password,
email: this.state.email
}, {
headers: {
'Content-Type': 'application/json'
}
}
}).then((res) => {
console.log(res);
}).catch(err => console.log(err));
}

Related

How to update component in user collection Strapi v4

[details="System Information"]
Strapi Version: 4.5.5
Operating System: Windows
Database: MySQL
Node Version: 14.20
NPM Version: 8.18.0
Yarn Version: 1.22.19
[/details]
Hi there, I'm trying to updata a component called "billingAddress" within my user collection. I have set up a route to be able to enable a user to update their own data based on this video: Updating Your Own User Info in Strapi - YouTube
I'm able to update user data but once I need to update data in the component I'm not able to update any data.
This is what my extension looks like on the strapi backend:
module.exports = (plugin) => {
plugin.controllers.user.updateMe = async (ctx) => {
if (!ctx.state.user || !ctx.state.user.id) {
return ctx.response.status = 401;
}
await strapi.query('plugin::users-permissions.user').update({
where: { id: ctx.state.user.id },
data: ctx.request.body,
}).then((res) => {
ctx.response.status = 200;
})
}
plugin.routes['content-api'].routes.push(
{
method: "PUT",
path: "/user/me",
handler: "user.updateMe",
config: {
prefix: "",
policies: []
}
}
)
return plugin;
}
This is the Axios put request I'm using to update the user data from the frontend:
const handleUpdateBillingAddress = () => {
axios.put('http://localhost:1337/api/user/me', {
billingAddress: {
zipCode: "2840",
id: 1,
firstName: "Tim",
lastName: "kerrem",
company: "mycompany",
address1: "mystreet 42",
address2: null,
city: null,
country: "Belgium",
provinceOrState: null,
zipCode: null,
phone: "+31412412412",
email: null
}
},
{
headers: {
'authorization': `Bearer ${jwt}`,
'Content-Type': 'application/json'
},
},
)
.then(response => {
console.log(response)
notification.open({
type: 'success',
message: 'Success!',
description:'Your user information has been updated',
});
})
.catch(error => {
console.log(error);
console.log('An error occurred:', error.response);
notification.open({
type: 'error',
message: 'Something went wrong',
description:'Some of your credentials are not valid',
});
});
}
Would be really helpful if someone could advise me on how to update the component
Hi you wanna try doing this via entityService strapi doc's states:
The Entity Service API is the recommended API to interact with your application's database. The Entity Service is the layer that handles Strapi's complex data structures like components and dynamic zones, which the lower-level layers are not aware of.
reference
so try:
await strapi.entityService.update('plugin::users-permissions.user', ctx.state.user.id, {data: ctx.request.body })
By using entityService and doing some tweaking with data and populate parameters I was able to get this working with following code:
module.exports = (plugin) => {
plugin.controllers.user.updateMe = async (ctx) => {
if (!ctx.state.user || !ctx.state.user.id) {
return ctx.response.status = 401;
}
const billingData = ctx.request.body.billingAddress;
await strapi.entityService.update('plugin::users-permissions.user', ctx.state.user.id, {
data: {
billingAddress: {
firstName: billingData.firstName,
lastName: billingData.lastName,
company: billingData.company,
address1: billingData.address1,
city: billingData.city,
country: billingData.country,
provinceOrState: billingData.provinceOrState,
zipCode: billingData.zipCode,
phone: billingData.phone,
email: billingData.email,
},
},
populate: ["billingAddress"],
}).then((res) => {
ctx.response.status = 200;
})
}
plugin.routes['content-api'].routes.push(
{
method: "PUT",
path: "/user/me",
handler: "user.updateMe",
config: {
prefix: "",
policies: []
}
}
)
return plugin;
}

send file and data to server with Axios

I am using ReactJs and wanna send data to Laravel API with Axios.
I try
export const send = (data, File) => {
const formData = new FormData();
formData.append('media', File);
try {
PostRequest.post('/post', { formData, data })
.then(r => console.log(r.data))
.catch(e => console.log(e));
} catch (error) {
console.log(error);
}
};
and I call send like this :
let data = {
mobile: mobile,
email: emailAddress,
userName: userName,
password: password,
firstName: firstName,
lastName: lastName,
website: website,
bio: bio,
date: selectedDay,
code: code,
};
console.log(profile);
console.log(data);
send(data, profile);
the log
but form data is null in the response
I set the header like this :
headers: {
"Content-Type": "multipart/form-data",
"Accept":"application/json"
}
also I try
const formData = new FormData();
formData.append('media', profile);
let data = {
mobile: mobile,
email: emailAddress,
userName: userName,
password: password,
firstName: firstName,
lastName: lastName,
website: website,
bio: bio,
date: selectedDay,
code: code,
media: formData,
};
send(data);
but the media is null
The problem is not with your implementation at all. You can't log the formData in the console and expect to see its entities as the other objects.
So, the empty formData on the console is proper behavior. if you really want to inspect your formData, take a look at this post.
thus, your send method is working properly and sending the correct data to the server.
Optional
On the server, you need to get the formData and parse it, so it must be implemented on the server-side. since you need to get the body request in formData, you could append all your data in the whitin a formData and send a single formData, but its depened on the backend implementation, if you can change the server-side, I engourage you to appnend all your data in the formData and then send it.
you can have an uploader like this , which will work with ;)
const Uploader = ({ url, updateData }) => {
function handleUpload(e) {
if (e.target.files[0]) {
console.log(e.target.files);
const formData = new FormData();
formData.append("config", e.target.files[0], e.target.files[0].name);
console.log(formData);
axios.post(url, formData).then(res => {
updateData(res);
});
}
}
return (
<label>
<div className={styles.uploaderBtn}>
<input
type="file"
style={{ display: "none" }}
onChange={e => {
handleUpload(e);
}}></input>
<img src={Upload} alt="" />
</div>
</label>
);
};

State not updating within a promised fetch (react)

I have a form with which i am sending data to my api. The data is used to create backend admin accounts and also create post entries. I need to post the data in a certain order to get some dynamic fields from the admin account to the post. For example:
create the admin account to make an id field
use the id field and apply to the post to create a unique link between admin account and post
Everything works apart from one state update that i'm trying to do after fetching the freshly created account:
// dont know what the ID will be as its dynamic
const [theID, setTheID] = useState('');
//Send the data to firstly create the admin account (works fine)
fetch('example.com/api/cockpit/saveUser', {
method: 'post',
headers: {
'Content-Type': 'application/json',
'Cockpit-Token': process.env.REACT_APP_API_KEY
},
body: JSON.stringify({
user: {
user: firstname.toLowerCase()+surname.toLowerCase(),
name: firstname,
email: email,
password: password,
group: 'consumers',
}
})
})
.then(user => user.json())
// make next fetch a chain of the promise
// fetch all accounts but filter by email so will only return the right one
.then(()=>{
return fetch(`example.com/api/cockpit/listUsers&filter[email]=${email}`,{
method: 'post',
headers: {
'Content-Type': 'application/json',
'Cockpit-Token': process.env.REACT_APP_API_KEY
}
})
})
.then((res) => {
return res.json();
})
.then((res)=>{
// the console log works fine
console.log(res[0]._id);
// the state returns undefined
setTheID(res[0]._id);
})
.catch((err)=>{
console.error(err);
})
//Then last fetch to make the post entry works fine ...
.then(()=>{
return fetch('example.com/api/collections/save/consumers', {
method: 'post',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Cockpit-Token': process.env.REACT_APP_API_KEY,
},
body: JSON.stringify({
data: {
firstname: firstname,
surname: surname,
password: password,
email: email,
project_name: projectName,
project_template: tmp,
// expected to get the dynamic ID front the state
ass_consumer: theID,
slug: projectName.toLowerCase().replace(' ','') + '-rr',
username: firstname.toLowerCase()+surname.toLowerCase()
}
})
})
})
.then(user => user.json())
.then((user)=>{
setnewPage(user._id);
})
I've checked the console which shows up fine after fetching. All my other state changes are bound to the form inputs but i've never had this problem with updating state in a fetch before.
I've also tried creating a function that takes the email as an argument then returns the state change but no luck with that either.
Appreciate any help!
(using cockpit as my api)
EDIT
This is what the console log returns:
(i just need the _id)
{
user: "johndoe",
name: "john",
email: "john.doe#example.com",
active: true,
group: "consumers", 
_created: 1627039008,
_id: "60faa5203365618a38000035",
_modified: 1627039008,
}
You are most likely reading the state within the same operation ("too quickly"), so the state changes will not be reflected yet because the process to update React state is asynchronous.
You have 2 options to always get the most up to date state value:
Either use a reference to the state (check out this package)
Or use an "ugly" work-around taking the value from setState like this:
const [id, setId] = useState("")
setId("test")
console.log(id) // ""
// do this to get the up to date value, as the value
// in setState is always the most up to date one
let idVal
setId(current => {
idVal = current
return current
})
console.log(idVal) // "test"
So in your specific example, try this:
//Then last fetch to make the post entry works fine ...
.then(()=>{
let customerID
setTheID(current => {
customerID = current
return current
})
return fetch('example.com/api/collections/save/consumers', {
method: 'post',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Cockpit-Token': process.env.REACT_APP_API_KEY,
},
body: JSON.stringify({
data: {
[...]
// use the customerID variable, not the state variable
ass_consumer: customerID,
[...]
}
})
})
})

Axios post request not working with Django Rest Framework

I am trying to use Axios post to create a user in my Django Rest Framework api.
Currently getting "Request failed with status code 400" when trying to post.
It works perfectly fine in postman.
drfServer.js
import axios from 'axios';
export default axios.create({
baseURL: 'https://example.com'
});
AuthContext.js
const signup = (dispatch) => async ({ email, password }) => {
try {
const response = await drfApi.post('/user/',
{
data: {
username: email,
password: password
}
}
);
// await AsyncStorage.setItem('token', response.data.token);
// dispatch({ type: 'signin', payload: response.data.token });
// navigate('Task')
} catch (err) {
console.log(err.message)
dispatch({ type: 'add_error', payload: 'Something went wrong with sign up' })
}
};
I tried using fetch and it works. But with Axios I am not getting it right.
Any ideas how to make it work?
Can you try this code.
const signup = ({email,password}) => dispatch => {
return axios({
method: "post",
url: "your api url",
data: {
username: email,
password
})
.then(result => {
console.log(result.data);
})
.catch(error => {
console.log(error);
})
};
You can find the axios example code here https://github.com/axios/axios
Maybe you can try this :
const response = await drfApi.post('/user/', {
username: email,
password: password
}
);
As using axios.post will automatically take the 2nd param and make it an object with data key

How to post query parameters with Axios?

I am trying to post on an API with some query params.
This is working on PostMan / Insomnia when I am trying to by passing mail and firstname as query parameters :
http://localhost:8000/api/mails/users/sendVerificationMail?mail=lol%40lol.com&firstname=myFirstName
However, when I am trying to do it with my react native app, I got a 400 error (Invalid Query Parameters).
This is the post method :
.post(`/mails/users/sendVerificationMail`, {
mail,
firstname
})
.then(response => response.status)
.catch(err => console.warn(err));
(my mail and firstname are console.logged as follow: lol#lol.com and myFirstName).
So I don't know how to pass Query Parameters with Axios in my request (because right now, it's passing data: { mail: "lol#lol.com", firstname: "myFirstName" }.
axios signature for post is axios.post(url[, data[, config]]). So you want to send params object within the third argument:
.post(`/mails/users/sendVerificationMail`, null, { params: {
mail,
firstname
}})
.then(response => response.status)
.catch(err => console.warn(err));
This will POST an empty body with the two query params:
POST
http://localhost:8000/api/mails/users/sendVerificationMail?mail=lol%40lol.com&firstname=myFirstName
As of 2021 insted of null i had to add {} in order to make it work!
axios.post(
url,
{},
{
params: {
key,
checksum
}
}
)
.then(response => {
return success(response);
})
.catch(error => {
return fail(error);
});
In my case, the API responded with a CORS error. I instead formatted the query parameters into query string. It successfully posted data and also avoided the CORS issue.
var data = {};
const params = new URLSearchParams({
contact: this.ContactPerson,
phoneNumber: this.PhoneNumber,
email: this.Email
}).toString();
const url =
"https://test.com/api/UpdateProfile?" +
params;
axios
.post(url, data, {
headers: {
aaid: this.ID,
token: this.Token
}
})
.then(res => {
this.Info = JSON.parse(res.data);
})
.catch(err => {
console.log(err);
});
You can use params and body together in a request with axios
sendAllData (data) {
return axios
.post(API_URL + "receiveData", JSON.stringify(data), {
headers: { "Content-Type": "application/json; charset=UTF-8" },
params: { mail: xyx#example.col }, //Add mail as a param
})
.then((response) => console.log("repsonse", response.status));
}

Categories