Reputation: 13
Fixed: I changed a few things in a go, so i can't really tell what solved my issue, but basically: -the API needed int or long and i was sending String.. parseInt solved it. I declared initially a data object:
const [data, setData] = useState({
})
With all the values i was gonna send later on(and with the correct data types! if i'm not sure, null seems to work pretty well for initialization).
-Another issue was that i merged all my data in a hook just before my POST request, since its asynchronous..it's a bad idea.
-Lastly, but most importantly, and that was probably the issue (thanks to EntiendoNull and JMadelaine), i initialized my data as [] and not as {}, so i was sending an object inside of an array.. hence the JSON parse error: Cannot deserialize instance of
message in the API when i POST.
.----------------------------------------------------------------------------------------------------------------------------------.
I've got an issue with a post request not working properly.
Basically, the header is not right, it should be {"content-type": "application/json"}
But instead, it's an empty object.
Here is where i do the POST:
const [data, setData] = useState([]);
const createMission = async (e) => {
setData({
...data,
nom:state.missionName,
id_client:state.currentClientKey,
id_consultant:state.currentConsultantId,
id_manager:1,
id_ro:state.currentROKey,
id_rc:state.currentRCKey,
detail:state.missionDescription,
adresse:state.adresse,
frequence_eval:6,
date_debut:state.startDate,
date_fin:state.endDate,
metier:state.metier
});
let headers = {
headers: {'Content-Type': 'application/json'}
};
axios.post('http://localhost:8080/mission',data,{"headers" : headers})
.then(res => {
console.log(res);
});
Here is the content of the res on the console of my navigator:
{…}
config: Object { url: "http://localhost:8080/mission", method: "post", data: "{\"nom\":\"\",\"id_consultant\":null,\"id_manager\":1,\"detail\":\"\",\"adresse\":\"\",\"frequence_eval\":6,\"date_debut\":null,\"date_fin\":null,\"metier\":null}", … }
data: ""
headers: Object { }
request: XMLHttpRequest { readyState: 4, timeout: 0, withCredentials: false, … }
status: 200
statusText: ""
<prototype>: Object { … }
The data is sent fine, I get a 200 status back, but as you can see, the headers have an empty object in it, and the data is an empty string ""
.
Funny thing is, I do almost the exact same thing on another component, and it works just fine : In this case, I don't even specify the headers.
const createClient = async (e) => {
axios.post('http://localhost:8080/client', {nom:state.nomClient})
.then(res => {
console.log(res);
});
};
And here is the log :
{…}
config: Object { url: "http://localhost:8080/client", method: "post", data: "{\"nom\":\"aze\"}", … }
data: Object { id: 372, nom: "aze" }
headers: Object { "content-type": "application/json" }
request: XMLHttpRequest { readyState: 4, timeout: 0, withCredentials: false, … }
status: 200
statusText: ""
<prototype>: Object { … }
The API is the same, it's a @RequestBody. Here for the mission :
@PostMapping
public Mission addMission (@RequestBody MissionBean missionBean){
Optional<Client> optionalClient = clientRepository.findById(missionBean.id_client);
Optional<Consultant> optionalConsultant = consultantRepository.findById(missionBean.id_consultant);
Optional<Utilisateur> optionalManager = utilisateurRepository.findById(missionBean.id_manager);
Optional<Utilisateur> optionalRo = utilisateurRepository.findById(missionBean.id_ro);
Optional<Utilisateur> optionalRc = utilisateurRepository.findById(missionBean.id_rc);
if (optionalClient.isPresent() && optionalManager.isPresent() && optionalConsultant.isPresent() && optionalRo.isPresent() && optionalRc.isPresent()){
Mission newMission = new Mission(
missionBean.nom,
optionalClient.get(),
optionalConsultant.get(),
optionalManager.get(),
optionalRo.get(),
optionalRc.get(),
missionBean.detail,
missionBean.adresse,
missionBean.frequence_eval,
missionBean.date_debut,
missionBean.date_fin,
missionBean.metier
);
missionRepository.save(newMission);
return newMission;
}
return null;
}
and here for the client(2nd example that works just fine) :
@PostMapping
public Client addClient (@RequestBody Client client){
clientRepository.save(client);
Critere critere = new Critere(client,"Ponctualité",true);
Critere critere2 = new Critere(client,"Assiduité",true);
Critere critere3 = new Critere(client,"Intégration",true);
critereRepository.save(critere);
critereRepository.save(critere2);
critereRepository.save(critere3);
return client;
}
I've tried many different ways to specify the headers, but it still doesn't work. The request works good(200), but the data is not being understood API side, no header, so an empty string as the data, I'm kind of new to this so I'm stuck here. When I check my Database nothing new has been added.
Edit: I got a message from the API each time i make the request :
2020-02-22 22:19:39.737 WARN 4205 --- [nio-8080-exec-7] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of `com.evalside.project.beans.MissionBean` out of START_ARRAY token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `com.evalside.project.beans.MissionBean` out of START_ARRAY token
at [Source: (PushbackInputStream); line: 1, column: 1]]
Maybe this can help pointing the issue
Edit2: Some of my values are supposed to be int but come as String(just noticed) Gonna fix that and try again
Upvotes: 1
Views: 1731
Reputation: 13
thanks for your help
First, the initial value of your data state should be an object (according do what kind of type and value you point it to be later). Better be clear with your intentions from start :)
const [data, setData] = useState({});
Actually it is, i wrote it like : const [data, setData] = useState([]);
not with {}.
I'm starting to get into hooks, so yep i don't have the right habits yet, i'm gonna try to use setDate(prevState => { // your logic })
more often.
I have several components all lifting some values into this one, which will eventually make the post request, that's why it's a bit messy with all the states and the data passing by, but i've tried many ways, and i've already tried simply doing :
const data = {name:myName, date:myDate etc..}
(...)
axios.post('url', data, headers)
I have other things happening i missed in the API, gonna add it to the post, maybe it'll help ;)
Upvotes: 0
Reputation: 1925
You probably do not want to use your state like that.
First, the initial value of your data state should be an object (according do what kind of type and value you point it to be later). Better be clear with your intentions from start :)
const [data, setData] = useState({});
Second, when updating a state the way you do may lead to problems.
Consider using setDate(prevState => { // your logic })
instead.
Third, from the code you are showing it does not make much sense to set your state the way you do and then feed it to your axios.post
request. Or is there any other reason why those values are stored in a state before being used in your request? Most of them seem to already be stored in some other state
already, right?
Instead, you could have declared a const
holding those values:
const myData = {
nom:state.missionName,
id_client:state.currentClientKey,
id_consultant:state.currentConsultantId,
id_manager:1,
id_ro:state.currentROKey,
id_rc:state.currentRCKey,
detail:state.missionDescription,
adresse:state.adresse,
frequence_eval:6,
date_debut:state.startDate,
date_fin:state.endDate,
metier:state.metier
}
Typically once your side effect is done and you have received a response is when you may want to update a state like this one.
Fourth, you did declare a headers
-object;
let headers = {
headers: {'Content-Type': 'application/json'}
};
So in your axios-request do this:
axios.post('http://localhost:8080/mission', data, headers);
instead of this:
axios.post('http://localhost:8080/mission',data,{"headers" : headers})
Upvotes: 1