Related
The initial state looks like:
const state = {
profile: [
{
form: {
name: "",
surname: "",
born_date: "",
phone_number: 0,
city: "",
title: "",
},
experience: [],
training: [],
languages: [],
abilities: [],
},
],
}
I just want to remove an object of experience array, and return the new array to state and refresh view without this item, but it doesn't work as expected, don't know how can i set the new array in experience: []
i tried some posibilities.
if (state.profile[0].experience.length > 1) {
let experiences = [...state.profile[0].experience];
let newExp = experiences.slice(0, action.payload).concat(experiences.slice(action.payload + 1)); //Slice works
experiences = { ...experiences, experience: newExp };
return {
...state,
profile: [...state.profile,[{ experience: newExp}]]
};
}
thx!
I have a login component that after the user have login, I went ahead to get the data to my local storage and if the login is successeful, which means the data is true, I want to update my component by redirecting the user another components and update my component with the user information. Right now the login went successfully and data been passed to the local storage, but, I don't get redirected, because in the next componet, the update is not happening. and in my console logs waning error that said "Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function."
here is my login component
const user = JSON.parse(localStorage.getItem("user"));
const applicationForm = {
firstname: "",
lastname: "",
middlename: "",
gender: "",
dob: "",
phone: "",
email: "",
country: "",
crr_state: "",
institution: "",
fac_dept: "",
year_entry: "",
matric_number: "",
student_status: "",
edu_level: "",
applying_as: "",
team_members: "",
idea_grant: "",
category: "",
current_status: "",
area_of_interest: "",
formStatus: "Save and Continur later",
id: user ? user._id : "",
idea_summary: "",
video_url: "",
textChange: "Sumbit",
};
const NUICAppForm = () => {
const [formData, setFormData] = useState(applicationForm);
const [states, setStates] = useState(null);
const categoryList = [
"Renewable Energy Technologies",
"Satellite Communication Technologies",
"Drone Technologies",
"E-commerce Development",
"Smart AgricTech",
"Mobile Computing and 5G Networks",
];
const {
firstname,
lastname,
middlename,
gender,
dob,
phone,
email,
country,
crr_state,
institution,
fac_dept,
year_entry,
matric_number,
student_status,
edu_level,
current_status,
applying_as,
team_members: {
memberFullname1,
memberEmail1,
memberPhone1,
memberFullname2,
memberEmail2,
memberPhone2,
memberFullname3,
memberEmail3,
memberPhone3,
memberFullname4,
memberEmail4,
memberPhone4,
memberFullname5,
memberEmail5,
memberPhone5,
},
idea_grant,
category,
area_of_interest,
idea_summary,
video_url,
formStatus,
id,
textChange,
} = formData;
const clear = () => {
window.localStorage.clear();
};
const handleSubmit = (e) => {
e.preventDefault();
setFormData({ ...formData, textChange: "Submitting" });
axios
.post("https://i-next-backend.herokuapp.com/nuic/form/register", {
firstname,
lastname,
middlename,
gender,
dob,
phone,
email,
country,
crr_state,
institution,
fac_dept,
current_status,
year_entry,
matric_number,
student_status,
edu_level,
applying_as,
team_members: {
memberFullname1,
memberEmail1,
memberPhone1,
memberFullname2,
memberEmail2,
memberPhone2,
memberFullname3,
memberEmail3,
memberPhone3,
memberFullname4,
memberEmail4,
memberPhone4,
memberFullname5,
memberEmail5,
memberPhone5,
},
idea_grant,
category,
area_of_interest,
idea_summary,
formStatus,
video_url,
id: user._id,
})
.then((res) => {
setFormData({
...formData,
firstname: "",
lastname: "",
middlename: "",
gender: "",
dob: "",
phone: "",
email: "",
country: "",
crr_state: "",
current_status: "",
institution: "",
fac_dept: "",
year_entry: "",
matric_number: "",
student_status: "",
edu_level: "",
applying_as: "",
team_members: {
memberFullname1: "",
memberEmail1: "",
memberPhone1: "",
memberFullname2: "",
memberEmail2: "",
memberPhone2: "",
memberFullname3: "",
memberEmail3: "",
memberPhone3: "",
memberFullname4: "",
memberEmail4: "",
memberPhone4: "",
memberFullname5: "",
memberEmail5: "",
memberPhone5: "",
},
idea_grant: "",
category: "",
area_of_interest: "",
idea_summary: "",
video_url: "",
id,
textChange: "Application submitted for review ",
formStatus: "Pending application",
});
setFormData({
...formData,
textChange: "Application Submitted",
formStatus: "Application Pendig",
});
})
.catch((err) => {
setFormData({
...formData,
firstname: "",
lastname: "",
middlename: "",
gender: "",
dob: "",
phone: "",
email: "",
country: "",
crr_state: "",
current_status: "",
institution: "",
fac_dept: "",
year_entry: "",
matric_number: "",
student_status: "",
edu_level: "",
applyisng_as: "",
team_members: {
memberFullname1: "",
memberEmail1: "",
memberPhone1: "",
memberFullname2: "",
memberEmail2: "",
memberPhone2: "",
memberFullname3: "",
memberEmail3: "",
memberPhone3: "",
memberFullname4: "",
memberEmail4: "",
memberPhone4: "",
memberFullname5: "",
memberEmail5: "",
memberPhone5: "",
},
idea_grant: "",
category: "",
area_of_interest: "",
idea_summary: "",
video_url: "",
formStatus: "",
id,
});
setFormData({ ...formData, textChange: err.response.data.message });
});
};
useEffect(() => {
const fetchStates = async () => {
const result = await axios(
"https://nigerian-states-info.herokuapp.com/api/v1/states"
);
setStates(result.data.data);
};
fetchStates();
}, [user]);
As you can see above in the useEffect, first I defined a function that check if the user exist outside the ueEffect which the chechking is true but can update when a user login, the I thought of using useState to passed that value but still, it did not works. Please any suggestion on how to update my component when the signin went through ?
Please help.....
Your useEffect only runs once and that is right after the component has been loaded. Right now its not aware of any other changes since you have given empty dependency array to it.
To suggest a solution in your case, why don't you just call
history.push("/application")
after you set the data to localStoare? That is after the line
localStorage.setItem("user", JSON.stringify(res.data));
and remove the useEffect
You can have a Force Update by React hooks.
Declare const [render, setRerender] = useState(false);
then call the following when you want to update the UI, setRerender(!rerender);
Basically I have a mongodb collection called 'people'
whose schema is as follows:
people: {
name: String,
friends: [{firstName: String, lastName: String}]
}
Now, I have a very basic express application that connects to the database and successfully creates 'people' with an empty friends array.
In a secondary place in the application, a form is in place to add friends. The form takes in firstName and lastName and then POSTs with the name field also for reference to the proper people object.
What I'm having a hard time doing is creating a new friend object and then "pushing" it into the friends array.
I know that when I do this via the mongo console I use the update function with $push as my second argument after the lookup criteria, but I can't seem to find the appropriate way to get mongoose to do this.
db.people.update({name: "John"}, {$push: {friends: {firstName: "Harry", lastName: "Potter"}}});
Assuming, var friend = { firstName: 'Harry', lastName: 'Potter' };
There are two options you have:
Update the model in-memory, and save (plain javascript array.push):
person.friends.push(friend);
person.save(done);
or
PersonModel.update(
{ _id: person._id },
{ $push: { friends: friend } },
done
);
I always try and go for the first option when possible, because it'll respect more of the benefits that mongoose gives you (hooks, validation, etc.).
However, if you are doing lots of concurrent writes, you will hit race conditions where you'll end up with nasty version errors to stop you from replacing the entire model each time and losing the previous friend you added. So only go to the latter when it's absolutely necessary.
The $push operator appends a specified value to an array.
{ $push: { <field1>: <value1>, ... } }
$push adds the array field with the value as its element.
Above answer fulfils all the requirements, but I got it working by doing the following
var objFriends = { fname:"fname",lname:"lname",surname:"surname" };
People.findOneAndUpdate(
{ _id: req.body.id },
{ $push: { friends: objFriends } },
function (error, success) {
if (error) {
console.log(error);
} else {
console.log(success);
}
});
)
Another way to push items into array using Mongoose is- $addToSet, if you want only unique items to be pushed into array. $push operator simply adds the object to array whether or not the object is already present, while $addToSet does that only if the object is not present in the array so as not to incorporate duplicacy.
PersonModel.update(
{ _id: person._id },
{ $addToSet: { friends: friend } }
);
This will look for the object you are adding to array. If found, does nothing. If not, adds it to the array.
References:
$addToSet
MongooseArray.prototype.addToSet()
Use $push to update document and insert new value inside an array.
find:
db.getCollection('noti').find({})
result for find:
{
"_id" : ObjectId("5bc061f05a4c0511a9252e88"),
"count" : 1.0,
"color" : "green",
"icon" : "circle",
"graph" : [
{
"date" : ISODate("2018-10-24T08:55:13.331Z"),
"count" : 2.0
}
],
"name" : "online visitor",
"read" : false,
"date" : ISODate("2018-10-12T08:57:20.853Z"),
"__v" : 0.0
}
update:
db.getCollection('noti').findOneAndUpdate(
{ _id: ObjectId("5bc061f05a4c0511a9252e88") },
{ $push: {
graph: {
"date" : ISODate("2018-10-24T08:55:13.331Z"),
"count" : 3.0
}
}
})
result for update:
{
"_id" : ObjectId("5bc061f05a4c0511a9252e88"),
"count" : 1.0,
"color" : "green",
"icon" : "circle",
"graph" : [
{
"date" : ISODate("2018-10-24T08:55:13.331Z"),
"count" : 2.0
},
{
"date" : ISODate("2018-10-24T08:55:13.331Z"),
"count" : 3.0
}
],
"name" : "online visitor",
"read" : false,
"date" : ISODate("2018-10-12T08:57:20.853Z"),
"__v" : 0.0
}
First I tried this code
const peopleSchema = new mongoose.Schema({
name: String,
friends: [
{
firstName: String,
lastName: String,
},
],
});
const People = mongoose.model("person", peopleSchema);
const first = new Note({
name: "Yash Salvi",
notes: [
{
firstName: "Johnny",
lastName: "Johnson",
},
],
});
first.save();
const friendNew = {
firstName: "Alice",
lastName: "Parker",
};
People.findOneAndUpdate(
{ name: "Yash Salvi" },
{ $push: { friends: friendNew } },
function (error, success) {
if (error) {
console.log(error);
} else {
console.log(success);
}
}
);
But I noticed that only first friend (i.e. Johhny Johnson) gets saved and the objective to push array element in existing array of "friends" doesn't seem to work as when I run the code , in database in only shows "First friend" and "friends" array has only one element !
So the simple solution is written below
const peopleSchema = new mongoose.Schema({
name: String,
friends: [
{
firstName: String,
lastName: String,
},
],
});
const People = mongoose.model("person", peopleSchema);
const first = new Note({
name: "Yash Salvi",
notes: [
{
firstName: "Johnny",
lastName: "Johnson",
},
],
});
first.save();
const friendNew = {
firstName: "Alice",
lastName: "Parker",
};
People.findOneAndUpdate(
{ name: "Yash Salvi" },
{ $push: { friends: friendNew } },
{ upsert: true }
);
Adding "{ upsert: true }" solved problem in my case and once code is saved and I run it , I see that "friends" array now has 2 elements !
The upsert = true option creates the object if it doesn't exist. default is set to false.
if it doesn't work use below snippet
People.findOneAndUpdate(
{ name: "Yash Salvi" },
{ $push: { friends: friendNew } },
).exec();
An easy way to do that is to use the following:
var John = people.findOne({name: "John"});
John.friends.push({firstName: "Harry", lastName: "Potter"});
John.save();
In my case, I did this
const eventId = event.id;
User.findByIdAndUpdate(id, { $push: { createdEvents: eventId } }).exec();
Push to nested field - use a dot notation
For anyone wondering how to push to a nested field when you have for example this Schema.
const UserModel = new mongoose.schema({
friends: {
bestFriends: [{ firstName: String, lastName: String }],
otherFriends: [{ firstName: String, lastName: String }]
}
});
You just use a dot notation, like this:
const updatedUser = await UserModel.update({_id: args._id}, {
$push: {
"friends.bestFriends": {firstName: "Ima", lastName: "Weiner"}
}
});
This is how you could push an item - official docs
const schema = Schema({ nums: [Number] });
const Model = mongoose.model('Test', schema);
const doc = await Model.create({ nums: [3, 4] });
doc.nums.push(5); // Add 5 to the end of the array
await doc.save();
// You can also pass an object with `$each` as the
// first parameter to use MongoDB's `$position`
doc.nums.push({
$each: [1, 2],
$position: 0
});
doc.nums;
// This is the my solution for this question.
// I want to add new object in worKingHours(array of objects) -->
workingHours: [
{
workingDate: Date,
entryTime: Date,
exitTime: Date,
},
],
// employeeRoutes.js
const express = require("express");
const router = express.Router();
const EmployeeController = require("../controllers/employeeController");
router
.route("/:id")
.put(EmployeeController.updateWorkingDay)
// employeeModel.js
const mongoose = require("mongoose");
const validator = require("validator");
const employeeSchema = new mongoose.Schema(
{
name: {
type: String,
required: [true, "Please enter your name"],
},
address: {
type: String,
required: [true, "Please enter your name"],
},
email: {
type: String,
unique: true,
lowercase: true,
required: [true, "Please enter your name"],
validate: [validator.isEmail, "Please provide a valid email"],
},
phone: {
type: String,
required: [true, "Please enter your name"],
},
joiningDate: {
type: Date,
required: [true, "Please Enter your joining date"],
},
workingHours: [
{
workingDate: Date,
entryTime: Date,
exitTime: Date,
},
],
},
{
toJSON: { virtuals: true },
toObject: { virtuals: true },
}
);
const Employee = mongoose.model("Employee", employeeSchema);
module.exports = Employee;
// employeeContoller.js
/////////////////////////// SOLUTION IS BELOW ///////////////////////////////
// This is for adding another day, entry and exit time
exports.updateWorkingDay = async (req, res) => {
const doc = await Employee.findByIdAndUpdate(req.params.id, {
$push: {
workingHours: req.body,
},
});
res.status(200).json({
status: "true",
data: { doc },
});
};
https://www.youtube.com/watch?v=gtUPPO8Re98
I ran into this issue as well. My fix was to create a child schema. See below for an example for your models.
---- Person model
const mongoose = require('mongoose');
const SingleFriend = require('./SingleFriend');
const Schema = mongoose.Schema;
const productSchema = new Schema({
friends : [SingleFriend.schema]
});
module.exports = mongoose.model('Person', personSchema);
***Important: SingleFriend.schema -> make sure to use lowercase for schema
--- Child schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const SingleFriendSchema = new Schema({
Name: String
});
module.exports = mongoose.model('SingleFriend', SingleFriendSchema);
i am trying to push array in document array my collection is
{
"_id": "58eed81af6f8e3788de703f9",
"first_name": "abc",
"vehicles": {
"exhibit": "18",
"title": "Motor Velicle Information for Donald French",
"details": [
{
"year": "",
"make_model": "",
"registered_owner": "",
"license_number": "",
"date_of_purchase": "",
"purchase_price": ""
}
]
}
}
so what i want is to push data in details for that i had try like this
Licensee.update({"_id":"58eed81af6f8e3788de703f9"},{
$push:{
"vehicles.details":data
}
},function(err,data){
if(!err)
{
console.log('data',data);
}
else
{
console.log('err',err);
}
});
and for this i create one schema i don't know is right or not
var licSchema = new SimpleSchema({
"_id":{
type:String,
label:"_id",
optional: false,
},
"vehicles.details.year": {
type: String,
label: "year",
optional: true,
},
"vehicles.details.make_model": {
type: String,
label: "make_model",
optional: true,
}
});
where is my fault please give me solution .
Error Uncaught Error: After filtering out keys not in the schema, your modifier is now empty
You can try this. AddToSet should be the right way.
const schema = new SimpleSchema({
"vehicles.details.$.year": {
type: String,
label: "year",
optional: true,
},
"vehicles.details.$.make_model": {
type: String,
label: "make_model",
optional: true,
}
});
Licensee.update({"_id":"58eed81af6f8e3788de703f9"},{
$addToSet:{
"vehicles.details": data
}
});
I have already checked the following stackoverflow questions:
Mongoose delete array element in document and save
How to remove array element in mongodb?
Here is what I tried:
var User = require('../model/user_model.js');
router.put('/favoritemovies/:id', function(req, res){
console.log(req.params.id);
console.log(req.body.email);//I am able to console.log both value
User.update( {_id: req.body.email}, { $pullAll: { favoriteMovies: {id:req.params.id} } } },
});
My user model:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId;
var userSchema = new Schema ({
id: ObjectId,
name: String,
password: String,
email: {type: String, unique: true},
favoriteMovies: []
});
module.exports = mongoose.model('users', userSchema);
This is the structure of my JSON object:
{
"_id": {
"$oid": "583893712f599701531b60bf"
},
"name": "",
"password": "",
"email": "",
"favoriteMovies": [
{
"vote_average": ,
"video": ,
"vote_count": ,
"popularity": ,
"backdrop_path": "",
"title": "",
"original_language": "",
"original_title": "",
"id": ,
"genre_ids": [],
"release_date": "",
"overview": "",
"adult": ,
"poster_path": "",
"_id": ""
}
I would like to delete one or more elements from the favoriteMovies array, if their ids' matches my id. I don't get any error message, but the the element don't get removed either.
What would be the proper request to achieve that?
$pullAll is used for removing multiple entries out an array, and takes an Array in its query.
You're only looking to remove one entry, so just use $pull.
{ $pull: { favoriteMovies: {id: req.params.id} } } }
It will work using pull, you're sure that the update condition is correct ?
{_id: req.body.email}
Regarding your example :
"_id": {
"$oid": "583893712f599701531b60bf"
},
It seems that you should use :
{email: req.body.email}
I found out the problem, I missed the callback function at the end of the query.
User.update( {_id: req.body.email}, { $pull: { favoriteMovies: { id: req.params.id} }
}, function(err, model){})