Push an object to an array in api in react onSubmit - reactjs

I have an api with the following schema.
[
{
"id":1,
"question": {
"description" : "",
"user": "",
},
"answers:[
{
"detailedAnswer" : "",
"user" : "",
},
{
"detailedAnswer" : "",
"user" : "",
}
]
},
{
"id":2,
"question": {
"description" : "",
"user": "",
},
"answers:[
{
"detailedAnswer" : "",
"user" : "",
}
]
}
]
So In my react app I need to add new object (given below) to the answers array of that particular id everytime I click submit button.
{
"detailedAnswer" : "",
"user" : "",
},
So my question is how can I push new object to the answers array ?
So, I tried Post method it shows "Bad request 400 error" and when I use "PUT" method, the object instead of appending item to the array replaces the exisitng object.
const postAnswer = async (e) => {
e.preventDefault();
const addAnswer = {
detailedanswer: answer,
user: user,
};
await fetch(`${API}/home/${id}`, {
method: "POST",
body: JSON.stringify(addAnswer),
headers: {
"Content-Type": "application/json",
},
})
.then((response) => {
response.json()
console.log(response)
})
.then((data) => {
console.log(data)
})
.then(() => alert("Answer added successfully"))
.then(() => navigate(`/home/${id}`))
.catch((err) => console.log(err.message))
}
This is the error I got
POST https://635b6c48aa7c3f113dbc75cb.mockapi.io/home/5 400 ( Bad Request )
Response {type: 'cors', url: 'https://635b6c48aa7c3f113dbc75cb.mockapi.io/home/5', redirected: false, status: 400, ok: false, …}
There is no error in the URL mentioned still I am getting bad request error.

Related

How to format API response

I'm writing a react app that fetches data from a DynamoDB table using a Lambda function. The function successfully retrieves an array of objects as shown below. I've tested this in the AWS console and in Postman.
[
{
"Obj1Key1": {
"S": "Obj1Value1"
},
"Obj1Key2": {
"S": "Obj1Value2"
},
"Obj1Key3": {
"S": "Obj1Value3"
},
"Obj1Key4": {
"S": "Obj1Value4"
}
},
{
"Obj2Key1": {
"S": "Obj2Value1"
},
"Obj2Key2": {
"S": "Obj2Value2"
},
"Obj2Key3": {
"S": "Obj2Value3"
},
"Obj2Key4": {
"S": "Obj2Value4"
}
},
{
"Obj3Key1": {
"S": "Obj3Value1"
},
"Obj3Key2": {
"S": "Obj3Value2"
},
"Obj3Key3": {
"S": "Obj3Value3"
},
"Obj3Key4": {
"S": "Obj3Value4"
}
}
]
..and below is the function in the React app that gets the data:
...
...
const [ response , setResponse ] = useState();
...
async function fetchData() {
try {
const body = JSON.stringify({
etc....
});
await fetch("https://url..etc", {
method: "POST",
headers: { "Content-Type": "application/json"},
body: body
}).then(res => setResponse(res))
} catch (error) {
console.log(error);
}
};
However When I get the raw response from the React app, and I console log it, my console shows the following
How can I get the array of objects from this response? I tried different combinations of parsing and stringifying but was not able to get the array as an array. Adding .then(res => res.text()). before .then(res => setResponse(res)) gets me the response I'm looking for but as a string. I need to get it as an array.
Thank you

React + fetch: adding extra characters and backslashes to my url

I have this code in React 17
useEffect(() => {
getLocalJson('../json/login/login.json', props.headers)
.then(resp => {
setFields(resp);
});
}, [props.headers]);
And the getLocalJson method is in a different file:
export const getLocalJson = async (url, headers) => {
console.log(url)
const resp = await fetch(url, {'headers': headers});
const json = await resp.json();
return json;
}
However the call to load the local JSON file from the public folder is:
Request URL: http://localhost:3000/json/login/%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5Clogin.json
Ths is the JSON
[
{
"order": 0,
"systemName": "title",
"friendlyName": "Login",
"dataType": {
"type": "TITLE"
}
},
{
"order": 1,
"required": true,
"systemName": "username",
"friendlyName": "Username",
"errorMsg": "Invalid username",
"dataType": {
"type": "TEXT"
}
},
{
"order": 2,
"required": true,
"systemName": "password",
"friendlyName": "Password",
"errorMsg": "Invalid password",
"dataType": {
"type": "PASSWORD"
}
},
{
"order": 3,
"systemName": "title",
"friendlyName": "Login",
"dataType": {
"type": "BUTTON",
"submit": true
}
}
]
And it makes the call over and over and over
This exact code works on my ubuntu dev box, but is failing as abovw on my windows box
I think there is some issue with the way you are passing down the headers, look into the documentation to have a better idea.
Put your function in the body of your component where you're using useEffect and wrap it with useCallback like this:
const getLocalJson = useCallback( async (url, headers) => {
console.log(url)
const resp = await fetch(url, {'headers': headers});
const json = await resp.json();
return json;
},[])

Axios send strange array to React

I geting the data back from my API in React from a post request and I get just the first object of the entire Array.prototype
My API for the upload:
router.post("/uploads", upload.any(), async (req, res) => {
try {
if (!req.files) {
res.send({
status: false,
message: "No file uploaded",
});
} else {
let data = req.files;
res.send({
status: true,
message: "Files are uploaded",
data: data,
});
}
} catch (error) {
res.status(500).send(err);
}
});
POSTMAN gives me back:
{
"status": true,
"message": "Files are uploaded",
"data": [
{
"fieldname": "uploads\n",
"originalname": "46335256.jpg",
"encoding": "7bit",
"mimetype": "image/jpeg",
"destination": "client/uploads/",
"filename": "46335256-2020-08-04.jpg",
"path": "client/uploads/46335256-2020-08-04.jpg",
"size": 19379
},
{
"fieldname": "uploads\n",
"originalname": "120360358.jpg",
"encoding": "7bit",
"mimetype": "image/jpeg",
"destination": "client/uploads/",
"filename": "120360358-2020-08-04.jpg",
"path": "client/uploads/120360358-2020-08-04.jpg",
"size": 78075
}
]
}
perfect!
this is my function in React to upload
const uploadFiles = () => {
uploadModalRef.current.style.display = "block"
uploadRef.current.innerHTML = "File(s) Uploading..."
for (let i = 0; i < validFiles.length; i++) {
const formData = new FormData()
formData.append("images", validFiles[i])
axios
.post("http://localhost:5000/api/db/uploads", formData, {
onUploadProgress: progressEvent => {
const uploadPercentage = Math.floor(
(progressEvent.loaded / progressEvent.total) * 100
)
...// code for graphic upload
},
})
.then(resp => {
console.log(resp.data.data)
resp.data.data.map(item => {
console.log(item)
})
})
.catch(() => {
... // code
}
}
and with this I get (from the console):
[{…}]
0:
destination: "client/uploads/"
encoding: "7bit"
fieldname: "images"
filename: "46335256-2020-08-04.jpg"
mimetype: "image/jpeg"
originalname: "46335256.jpg"
path: "client/uploads/46335256-2020-08-04.jpg"
size: 19379
__proto__: Object
length: 1
__proto__: Array(0)
is an array(if I map it works) but with just the first object.
How is it possible ??
I tried even with async/await but nothing changes
Where I'm mistaking?
Thanks!

Couldn't able to post the data in reactjs (showing 400 BAD REQUEST)

my objective is to send the data but it is showing 400 BAD REQUEST, i don't know where i'm going wrong. I know it's a small thing but couldn't able to figure it out where i'm going wrong.
Here is the API format:
{
"id": "string",
"class": "string",
"count": 0,
"students": [
{
"studentsId": "string",
}
]
}
I wrote in this way:
let obj = {
"id": this.state.id,
"class": this.state.sclass,
"count": this.state.classStud.length,
"studentsId": this.state.classStud.map(stud=> stud.id)
}
axios.post(`/api/Students`, obj, {
headers: { 'Content-Type': 'application/json' }
})
.then(res => {
console.log(res)
console.log(res.data);
})
.catch((err) => {
console.log(err)
})
classStud JSON data would be in this format:
email: "abc#gmail.com"
class: null
id: "45wer154587jh87"
name: "AB C"
Can anyone help me where i'm going wrong?
Your request data is not in accordance with the API format which is why you get 400 BAD REQUEST.
You need to sent students data as an array of object with each object having key as studentsId. You can change how you prepare you data like below
let obj = {
"id": this.state.id,
"class": this.state.name,
"count": this.state.classStud.length,
"students": this.state.classStud.map(stud=> ({stundentsId: stud.id}))
}
try to change this line
"studentsId": this.state.classStud.map(stud=> stud.id)
to this
"students": this.state.classStud.map(stud=> {
return {
"studentsId" :stud.id
}
})

Mongoose Update array in a document does not work as expected

I'm scratching my head since a couple day on how to update the content of an array with Mongoose.
Here is my schema to begin with:
const playedGameSchema = new Schema ({
created: Date,
updated: Date,
game: {
type: Schema.Types.ObjectId,
ref: 'game'
},
creator: {
id: {
type: Schema.Types.ObjectId,
ref: 'user'
},
score: Number
},
partners: [{
id: {
type: Schema.Types.ObjectId,
ref: 'user'
},
score: Number
}]
});
module.exports = mongoose.model('PlayedGame', playedGameSchema);
Basically, what I want to achieve is to, at the same time:
- Update the creator.score (successful with dot notation).
- Update the score key for each partner (unsuccessful).
Here is the result of a document created:
{
"creator": {
"id": "5b8544fa11235d9f02a9b4f1",
"score": 0
},
"_id": "5bb6375f5f68cc5c52bc93ae",
"game": "5b45080bb1806be939bfde03",
"partners": [
{
"_id": "5bb637605f68cc5cafbc93b0",
"id": "5b85497111235d677ba9b4f2",
"score": 0
},
{
"_id": "5bb637605f68ccc70ebc93af",
"id": "5b85497111235d677ba9b4f2",
"score": 0
}
],
"created": "2018-10-04T15:53:03.386Z",
"updated": "2018-10-04T15:53:03.386Z",
"__v": 0
}
As I said, I was able to change the score of the score creator by passing something like { "creator.score": 500 } as a second parameter, then I switch to trying to update the array.
Here is my lambda function to update the score for each partner:
export const update: Handler = (event: APIGatewayEvent, context: Context, cb: Callback) => {
context.callbackWaitsForEmptyEventLoop = false;
const body = JSON.parse(event.body);
let partnersScore: object = {};
if(body.update.partners) {
body.update.partners.forEach((score, index) => {
const key = `partners.${index}.$.score`;
partnersScore = Object.assign(partnersScore, { [key]: score});
console.log(partnersScore);
});
}
connectToDatabase().then(() => {
console.log('connected', partnersScore)
PlayedGame.findByIdAndUpdate(body.id, { $set: { partners: partnersScore } },{ new: true})
.then(game => cb(null, {
statusCode: 200,
headers: defaultResponseHeader,
body: JSON.stringify(game)
}))
.catch(err => {
cb(null, {
statusCode: err.statusCode || 500,
headers: { 'Content-Type': 'text/plain' },
body: err
})});
});
}
Which passes a nice { 'partners.0.$.score': 500, 'partners.1.$.score': 1000 } to the $set.
Unfortunately, the result to my request is a partners array that contains only one empty object.
{
"creator": {
"id": "5b8544fa11235d9f02a9b4f1",
"score": 0
},
"_id": "5bb6375f5f68cc5c52bc93ae",
"game": "5b45080bb1806be939bfde03",
"partners": [
{
"_id": "5bb63775f6d99b7b76443741"
}
],
"created": "2018-10-04T15:53:03.386Z",
"updated": "2018-10-04T15:53:03.386Z",
"__v": 0
}
Can anyone guide me into updating the creator score and all partners score at the same time?
My thoughs about findOneAndUpdate method on a model is that it's better because it doesn't require the data to be changed outside of the BDD, but wanting to update array keys and another key seems very difficult.
Instead, I relied on a set/save logic, like this:
PlayedGame.findById(body.id)
.then(game => {
game.set('creator.score', update.creatorScore);
update.partners.forEach((score, index) => game.set(`partners.${index}.score`, score));
game.save()
.then(result => {
cb(null, {
statusCode: 200,
headers: defaultResponseHeader,
body: JSON.stringify(result)
})
})
.catch(err => {
cb(null, {
statusCode: err.statusCode || 500,
headers: { 'Content-Type': 'text/plain' },
body: JSON.stringify({ 'Update failed: ': err })
})});
})

Resources