DELETE request in redux - node.js

I'm writing a React Redux CRUD App with Node.js API. I'm struggling with DELETE part.
I'm receiving the successful delete message but nothing has changed in my database. Successful Message in Console
I just wonder why it's not deleting any data?
user.reducer :
import { userConstants } from '../_constants';
export function users(state = {}, action) {
switch (action.type) {
case userConstants.GETALL_REQUEST:
return {
loading: true
};
case userConstants.GETALL_SUCCESS:
return {
items: action.users
};
case userConstants.GETALL_FAILURE:
return {
error: action.error
};
case userConstants.DELETE_REQUEST:
// add 'deleting:true' property to user being deleted
return {
...state,
items: state.items.map(user =>
user.id === action.id
? { ...user, deleting: true }
: user
)
};
case userConstants.DELETE_SUCCESS:
// remove deleted user from state
return {
items: state.items.filter(user => user.id !== action.id)
};
case userConstants.DELETE_FAILURE:
// remove 'deleting:true' property and add 'deleteError:[error]' property to user
return {
...state,
items: state.items.map(user => {
if (user.id === action.id) {
// make copy of user without 'deleting:true' property
const { deleting, ...userCopy } = user;
// return copy of user with 'deleteError:[error]' property
return { ...userCopy, deleteError: action.error };
}
return user;
})
};
default:
return state
}
}
user_actions:
export const userService =
{
delete: _delete,
};
function _delete(id) {
const requestOptions = {
method: 'DELETE',
// headers: authHeader(),
};
return fetch(`/removeadmin/${id}` , requestOptions).then(handleResponse);
}
AdminListPage component :
delete(){
this.props.dispatch(userActions.delete(this.state.delete_user._id));
}
Also, in server-side I'm receiving a successful delete status
ServerSide Console(200)
Server_Side router:
app.delete('/removeadmin/:id', function(req, res)
{
var sent_url = url.parse(req.url, true),
qdata = sent_url.query,
sent_id = qdata.id;
console.log('id ' + sent_id);
admin.removeadmin(sent_id, function(err, user) {
if (err)
throw err;
});
Server_Side delete function:
module.exports.removeadmin = function(id, callback){
var query = { _id: id };
Admin.remove(query, callback);
};
I have deleted a user by simple fetch command in the component without redux and I have sent id in the body of delete request and it was working but with redux just successful message.
Thank you for any help

Your code in the post should work except for the fetch request the url should be prepended with the backend url so if the backend url is localhost:3000 your fetch should be:
return fetch(`http://localhost:3000/removeadmin/${id}`,
requestOptions).then(handleResponse);
and in your serverside router you can access your id param like so:
app.delete('/removeadmin/:id', function(req, res)
{
var send_id = req.params.id;
admin.removeadmin(sent_id, function(err, user) {
if (err)
throw err;
});

I have found that I made a mistake in URL. So on the server in URL I can't have access to my id and it showed me undefined.
Just I have changed these lines :
user_action:
return fetch(`/removeadmin?id=${id}` , requestOptions).then(handleResponse);
and server_side router:
app.delete('/removeadmin?:id', function(req, res){

Related

I'm trying to run this code but it is still sending me the error can't not set headers after they are already send to the client here is my code

router.post("/check", async (req, res) => {
const nom = req.body.nom
const postnom = req.body.postnom
const matricule = req.body.matricule
const numeroBordero = req.body.numero_bordero
const paymentOrder = req.body.payementOrder
const etudiant = Etudiant.findOne({ matricule }, function (err, result) {
if (result == null) {
req.flash("test", "veuillez entrer des infos correctes")
res.redirect("/");
} else if (result !== null) {
if (result.isRegistered !== true) {
Etudiant.updateOne({
_id: result._id
}, {
isRegistered: true
}, function (err) {
if (err) {
console.log(err);
} else {
console.log("correctly updated");
}
})
}
}
})
return res.render("profil", {
etudiant
});
})
Once you call redirect, you cannot call render.
Return after your redirect.
res.redirect("/");
return
What front end framework are you using and what are you trying to accomplish with this endpoint? It seems like the function is checking the value of the request for a record, the running an update if a record was found.
If you want the render on the ui to be conditional on the result of this api call, you need to render separate html accordingly.
I am used to using react or angular, where I simply send a json object to the UI, and let the ui determine which page to navigate to, or which component to conditionally render.
use return res.redirect("/"); instead
You want use async/await but only async is present in your code.
Next, use result === null instead of result == null.
I didn't test your code, but can you run this code ? I think it'll solve your issue.
This code use promises.
router.post("/check", (req, res) => {
const nom = req.body.nom
const postnom = req.body.postnom
const matricule = req.body.matricule
const numeroBordero = req.body.numero_bordero
const paymentOrder = req.body.payementOrder
Etudiant.findOne({ matricule }, function (err, result) {
if (result === null) {
req.flash("test", "veuillez entrer des infos correctes")
res.redirect("/");
} else if (result !== null) {
if (result.isRegistered !== true) {
Etudiant
.updateOne(
{_id: result._id},
{ isRegistered: true}
)
.then(() => {
console.log("correctly updated")
})
.catch((err) => {
console.log(err)
})
}
})
})

How do I get useState to render each time I update the state?

I have a level up bar, where if you click the plus button it increases the bar by 10%.
I am using useEffect to grab the skills of a specific user by filtering what I get back from mongoDB(Mongoose).
I created a refreshHandler callback function that I calling to increment refresh, so that useEffect would make a request again to my back-end and I was hoping it would render the component again.
It does this once at start, then one more time and then stops rendering. (The changes are still happening in the Database, although the level only goes up one time when clicked)
App.js
function App() {
// States
const [inputText, setInputText] = useState('');
const [skills, setSkills] = useState([]);
const [session, setSession] = useState({ auth: false, token: '', user_id: '', refresh: 0 });
var { isLoggedIn, refresh } = session;
const userAuth = (data) => {
setSession({
auth: true,
token: data.token,
user_id: data.user_id,
});
console.log('User logged in successfully!');
};
const refreshHandler = () => {
setSession({ ...session, refresh: session.refresh + 1 });
};
useEffect(() => {
console.log('USE EFFECT MOUNTED!!');
const fetchSkills = async () => {
const response = await axios.get('http://localhost:3001/api/users/fetchSkills');
console.log('response: ', response.data);
setSkills(
response.data.filter((skill) => {
if (skill.user_id == session.user_id) {
return skill;
}
})
);
};
fetchSkills();
}, [refresh]);
This is the skill.js component that I am using in my skillList component to show a list of skills.
skill.js
const Skill = ({ refreshHandler, text, level, skills, skill, setSkills, percent }) => {
const levelUpHandler = async () => {
let data = { _id: skill._id, level: skill.level, percent: skill.percent };
if (skill.percent == 90) {
data.percent = 0;
data.level += 1;
} else {
data.percent += 10;
}
const response = await axios
.put('http://localhost:3001/api/users/update-skill', data)
.then(console.log(data))
.catch((err) => console.log(err));
refreshHandler();
};
I tried using an example of useRef that I found but that ended up rendering/making the axios request in a loop.
Node.js backend - route
router.put('/update-skill', function (req, res) {
var id = req.body._id;
var update = { level: req.body.level, percent: req.body.percent };
console.log(update);
Skill.findByIdAndUpdate(id, update, { new: true }, (err, res) => {
if (err) {
console.log(err);
} else {
console.log('Success:', res);
}
});
});
MAIN GOAL:
Each time button is clicked, update the percent/level of skill in the back-end(mongoose/ mongoDB Atlas - This is working but only one request per skill, the skill goes from 0 to 10% then each consecutive click console.logs() 10% instead of going up).
Would like to see the progress bar increase each time button is clicked.
Any help would be greatly appreciated and as if more info is needed for the problem to be clear please let me know.
I figured out the solution to my problem!
Basically when I was making a put request using axios to my backend, the request was being sent but no response was given from the backend.
Diagnosed by checking the network tab and it had a pending for the request. It seems after 5 pending request the database stalls.
So to fix it I added a return statement.
router.put("/update-skill", async (req, res) => {
var id = req.body._id;
var update = { level: req.body.level, percent: req.body.percent };
try {
var responseData = await Skill.findByIdAndUpdate(id, update, { new:
true });
} catch (err) {
return res
.status(500)
.json({ error: "skill was not updated", message: err });
}
// This was the missing code I needed!
return res.json({ response: "Successful", data: responseData });
});

Save in mongodb and pass created object to a function

I'm beginner at programing and I don't know how can I do something with the mongoose save result.
In my post endpoint I would like to not save and directly return but instead of it I would like to do something with the result of save method like take the _id value of the new object created and pass to a function.
Here's what my post endpoint is doing and I would like to after saving not return but instead call a function passing the checkout object created:
router.post('/', async function(req, res) {
const { checkinId, eventId, email } = req.body;
let CheckoutTest = {
checkinId: checkinId,
eventId: eventId,
email: email,
}
const newCheckout = new Checkout(CheckoutTest);
await newCheckout.save((err, checkout) => {
if(err) {
return res.status(400)
.send(err);
}else {
return res.status(200)
.json({message: "Checkout successfully added!", checkout});
}
})
});
An elegant way to do this would be to add a try...catch block
router.post('/', async function(req, res) {
const { checkinId, eventId, email } = req.body;
let CheckoutTest = {
checkinId: checkinId,
eventId: eventId,
email: email,
}
const newCheckout = new Checkout(CheckoutTest);
try {
const newCheckoutObject = await newCheckout.save()
// Call the function that you wanted to after the save.
// You can pass in the "_id" of the object as shown here
const newData = await functionToBeCalled(newCheckoutObject._id)
return res.status(200).json({message: "Checkout successfully added!", newData});
} catch (err) {
return res.status(400).send(err);
}
}

POST data with user details in mongo db using node.js

I am developing a web application using the MEAN stack with Angular 6. I have a form to submit data into MongoDB. Following is the save function and it works.
It saves the extruded value in the DB.
saveExtrudedHeightValue(extrudedHeight: NgForm) {
if (extrudedHeight.value != "" && extrudedHeight.value != null) {
this.extrudedHeightService.saveExtrudedHeight(extrudedHeight.value).subscribe(res => {
console.log(res);
}, (err) => {
console.log(err);
});
}
}
Here is the model
// Schema for extruded height panel
var extrudedHeightSchema = new mongoose.Schema({
userName: {
type: String
},
extrudedHeight: {
type: Number
},
});
module.exports = mongoose.model('extrudedHeightValue', extrudedHeightSchema);
Here is my post route
//post extrudedHeight values
router.post("/save", function(req, res) {
var mod = new extrudedHeight(req.body);
extrudedHeight.findOneAndUpdate({
userName: req.body.email,
extrudedHeight: req.body.extrudedHeight,
},
req.body, {
upsert: true,
new: true
},
function(err, data) {
if (err) {
console.log(err);
res.send(err);
} else {
res.send(mod);
}
}
);
});
Here is the service.
// service for save extruded height
saveExtrudedHeight(extrudedHeight): Observable < any > {
return this.http.post('/extrudedHeight/save', extrudedHeight, httpOptions)
.pipe(
catchError(this.handleError)
);
}
Now I want to save data in DB with the current user's userName. I can retrieve the current user's userName by this.
this.payload.user['email']
My problem is that I do not have an idea how to pass this userName to post route to save in db.
Here is where I get token.
this.authService.onTokenChange().subscribe(
(token: NbAuthJWTToken) => {
if (token.isValid()) {
this.user = token.getPayload().user;
this.payload = token.getPayload();
console.log(this.payload.user['email']);
}
}
)
You can first call this.authService.onTokenChange inside the saveExtrudedHeight method, and then use the flatMap operator to unwrap the internal Observable that would be returned by the http.post.
That would translate to code like this:
import { flatMap } from 'rxjs/operators';
import { throwError } from 'rxjs';
...
saveExtrudedHeight(extrudedHeight): Observable<any> {
const requestPayload = {
extrudedHeight
};
return this.authService.onTokenChange()
.pipe(flatMap(
(token: NbAuthJWTToken) => {
if (token.isValid()) {
this.user = token.getPayload().user;
this.payload = token.getPayload();
const email = this.payload.user['email'];
requestPayload.email = email;
// Make the changes here to send the email as the Request Payload.
return this.http.post('/extrudedHeight/save', requestPayload, httpOptions)
.pipe(
catchError(this.handleError)
);
} else {
throwError('Something went wrong!');
}
}
));
}
PS: I'm not really sure if this would work though as I haven't tested it out and I can't without a minimal working StackBlitz.

Mongodb not updating the data after put request returns successful

In trying to use the objectid in the mongoose schema as a reference to do a put to update a document in a collection. The console logs its as a success but when I refresh the page or look in the mongo shell nothing changes.
Heres the put in the expressjs router:
router.put('/messageupdate/:empId', function (req, res) {
var values = req.body;
console.log(values);
var empId = req.params.empId;
console.log(empId);
Message.update({empId: empId}, values, function(err, values) {
if (!err) {
res.json("okay");
} else {
res.write("fail");
}
});
})
Heres the service method:
updateServiceWithId(message: Message): Observable<any> {
console.log(message);
const body = JSON.stringify(message);
console.log(body);
const headers = new Headers({'Content-Type': 'application/json'});
return this.http.put('http://localhost:3000/messageupdate/:empId', body, {headers: headers});
}
Heres the client side method that triggers the put:
onUpdateMessage() {
var retVal = confirm("Do you want to continue ?");
if( retVal == true ){
const message = new Message(this.fname,this.lname,this.empId,this.number,this.occu);
console.log(this.fname);console.log(this.lname);
console.log(this.empId);console.log(this.occu);
this.messages.push(message);
this.messageService.updateServiceWithId(message)
.subscribe(
() => console.log('Success!'),
error => console.error(error)
);
}
else{
alert("Edit cancled!");
return false;
}
}

Resources