Multiselect returns only one option - reactjs

im trying to get the options selected but im getting only the last selected option from the select input..
state never gets updated to multiple options..just the last option ,ive tried many options but nothing is saving the multile options.
currentPage: 3,
custFirstname: "",
custLastName: "",
custPhoneNum: "",
custEmail: "",
vehicleNum: "",
vehicleMake: "",
vehicleModel: "",
defects_tank: "",
defects_tankLogo: "",
defects_lightglass: "",
defects_seatcover: "",
defects_crashgaurd: "",
defects_mirrors: "",
defects_indicators: "",
electricals_headlight: "y",
electricals_tailLight: "y",
electricals_console: "y",
electricals_indicatorF: "y",
electricals_indicatorR: "y",
electricals_horn: "y",
petrolLevel: "",
battery: "",
jobs: [],
job: {
description: "",
repObserv: "",
customerReq: "",
typeOfService: "",
charges: "",
services: []
}
};
im updating the state -> job -> services
handleJobsDropDown = e => {
console.log(e.target.options);
const { options } = e.target;
const value = [];
for (let i = 0, l = options.length; i < l; i++) {
if (options[i].selected) {
value.push(options[i].value);
}
}
this.setState({
job: { ...this.state.job, services: value }
});
};
<select
multiple={true}
value={this.state.job.services}
onChange={this.handleJobsDropDown}
>
<option value="paid">Paid Serv</option>
<option value="free">Free Serv</option>
<option value="chain">Chain Serv</option>
<option value="repeat">Rpt Serv</option>
</select>

Related

Updating an array of objects in react redux

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!

How to update my UseEffect component to render new UI after a successful user login

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);

Typescript merging 2 arrays and increase qty if they have the same id

I'm doing with my Angular 8 project and I want to merge 2 arrays into 1 and increase qty if they have the same value in the object. I have tried a few times by myself and it does not really work well.
mergedOrderList: any[]= [];
lstOldOrder: any[] = [
{id: "", products_id: "", qty: 1, ...},
{id: "", products_id: "", qty: 1, ...},
{id: "", products_id: "", qty: 1, ...},];
lstNewOrder: any[] = [
{id: "", products_id: "", qty: 1, ...},
{id: "", products_id: "", qty: 1, ...},
{id: "", products_id: "", qty: 1, ...},];
lstNewOrder.forEach(newOrder => {
let isDubplicated: boolean = false;
lstOldOrder.forEach(oldOrder => {
if (newOrder.products_id == oldOrder.products_id) {
oldOrder.qty += newOrder.qty;
isDubplicated = true;
mergedOrderList.push(oldOrder);
}
});
if (!isDubplicated) {
mergedOrderList.push(newOrder)
}
});
I did like this and they work when they both have the same products_id. But when new order doesn't have products_id. They skip my old order and add only new order to the list. I'm not quite sure I'm done it right. Thanks
See the problem is that you are only adding data from lstOldOrder in mergedOrderList if the
product_id of new list item matches with any item in old list.
So you are not able to see any item from old list if all the items are new in lstNewOrder
Instead what you should do is :
Add the item to the mergedOrderList but increase the quantity if there is a match.
mergedOrderList = [];
lstOldOrder = [
{ id: "1", products_id: "", qty: 1 },
{ id: "2", products_id: "", qty: 1 },
{ id: "3", products_id: "", qty: 1 },
];
lstNewOrder = [
{ id: "4", products_id: "", qty: 1 },
{ id: "5", products_id: "", qty: 1 },
{ id: "1", products_id: "", qty: 1 },
];
lstNewOrder.forEach((newOrder) => {
Oindex = -1;
lstOldOrder.forEach((item, index) => {
if (item.id == newOrder.id) {
Oindex = index; // Getting the Index of that item in old array.
}
});
if (Oindex != -1) { // if that item was in old Array
newOrder.qty += lstOldOrder[Oindex].qty; // Increase Quantity in newOrderItem
lstOldOrder.splice(Oindex, 1); // Delete that Item from OldArray
}
mergedOrderList.push(newOrder); // Add the Item in Merged
});
mergedOrderList.concat(lstOldOrder); // Finally add all the remaining Items
All the edge cases in the code are not handled properly sorry for that.
Feel free to edit my answer, it may help someone else

Reading from a text file in swift and dealing with white space

I'm learning Swift and I'd just like to know the best way to go about reading in a text file, breaking it up into lines and then taking each word on each line and turn the words into strings that can be loaded into class initialisers.
For example, if I have this text file:
**This is just a random text file, and the text on this line
and this line is not needed**
birth year birth month birth day favourite colour
1990 11 12 red
1995 2 4 pink
1992 5 3 orange
1987 3 19 blue
I want to take the birth year, birth month, birth day and favourite colour from each line and then load it into a class like this:
Person(birthYear: 1990, birthMonth: 11, birthDay: 12, favouriteColour: red)
The text file that I want to read in might have an uneven amount of spaces so the output will look like this (for the given text file):
["**This", "is", "just", "a", "random", "text", "file,", "and", "the", "text", "on", "this", "line"]
["and", "this", "line", "is", "not", "needed**"]
["birth", "year", "", "", "", "birth", "month", "", "", "birth", "day", "", "", "", "", "favourite", "colour"]
["1990", "", "", "", "", "", "", "", "", "", "11", "", "", "", "", "", "", "", "", "", "", "", "12", "", "", "", "", "", "", "", "", "", "", "", "red"]
["1995", "", "", "", "", "", "", "", "", "", "", "2", "", "", "", "", "", "", "", "", "", "", "", "", "4", "", "", "", "", "", "", "", "", "", "", "", "pink", ""]
["1992", "", "", "", "", "", "", "", "", "", "", "5", "", "", "", "", "", "", "", "", "", "", "", "", "3", "", "", "", "", "", "", "", "", "", "", "", "orange"]
["1987", "", "", "", "", "", "", "", "", "", "", "3", "", "", "", "", "", "", "", "", "", "", "", "19", "", "", "", "", "", "", "", "", "", "", "", "blue"]
Here is my code so far:
let path = "path to my file"
if let contents = try? String(contentsOfFile: path) {
// breaking the text file up into lines
let lines = contents.components(separatedBy: "\n")
// breaking the lines up into wordsw
for line in lines {
let elements = line.components(separatedBy: " ")
print(elements)
}
}
I'm just wondering what the best way to deal with white space in these cases would be. Thank you in advance for your replies.
You can use a simple solution to clean all Tabs and Double spaces. Try use this piece of code.
func cleanTabsAndSpace(in text:String) -> String {
var newText = text
newText = newText.filter{ $0 != "\t" }.reduce(""){ str, char in
if let lastChar = str.last, lastChar == " " && lastChar == char {
return str
}
return str + String(char)
}
return newText.trimmingCharacters(in: .whitespacesAndNewlines)
}
After create this function you can call it inside your function
if let contents = try? String(contentsOfFile: path) {
// Clean undesired chars
let cleanContent = cleanTabsAndSpace(in: contents)
// breaking the text file up into lines
let lines = cleanContent.components(separatedBy: "\n")
// breaking the lines up into wordsw
for line in lines {
let elements = line.components(separatedBy: " ")
print(elements)
}
}
With this you will have all your content separated as you wish. Now you have just to follow as you want, parsing the content as you want and create your objects.
I'm just considering this structure you described in your question.
Good luck friend and Feel free to contact me if you need something more.
There is a split(separator:maxSplits:omittingEmptySubsequences:)
method which allows to split a String
into an array of SubStrings.
In contrast to components(separatedBy:) this method (by default)
omits empty substrings caused by consecutive separator characters.
Example:
let line = "1990 11 12 red"
let elements = line.split(separator: " ")
print(elements) // ["1990", "11", "12", "red"]
Here element has the type [SubString], i.e. the substrings reference
the original character storage in line, without duplicating it.
If you need "real" strings, then change it to
let elements = line.split(separator: " ").map(String.init)
Applied to your case:
if let contents = try? String(contentsOfFile: path) {
let lines = contents.components(separatedBy: "\n")
for line in lines {
let elements = line.split(separator: " ")
print(elements)
}
}

Array sorting by property

I have a set of object array like this:
[ProductDetails(name: "Tai Tou Choy",
productDescription: "",
deliveryTime: "24 hours",
img1: "https://api.com.my/images/data/4983-img1-1463122485.jpg",
thumbImg1: "https://api.com.my/images/data/thumbs/4983-img1-1463122485.jpg",
img2: "",
thumbImg2: "",
img3: "",
thumbImg3: "",
videoLink: "",
sku: "0000000004983",
relatedProduct: "",
priceOption: [PriceOption(id: 9931,
label: "500g",
price: "4.56",
promo: "0",
quantity: 999)],
deliveryZone: [DeliveryZone(zone: "3")],
deliveryZoneName: [DeliveryZoneName(zoneName: "Within Klang Valley")],
qrCode: "4983"),
ProductDetails(name: "Penguin Asam Jawa",
productDescription: "",
deliveryTime: "24 hours",
img1: "https://api.com.my/images/data/1004-img1.jpg",
thumbImg1: "https://api.com.my/images/data/thumbs/1004-img1.jpg",
img2: "",
thumbImg2: "",
img3: "",
thumbImg3: "",
videoLink: "",
sku: "0000000001004",
relatedProduct: "",
priceOption: [PriceOption(id: 6971,
label: "1 kg",
price: "4.80",
promo: "0",
quantity: 864)],
deliveryZone: [DeliveryZone(zone: "3")],
deliveryZoneName: [DeliveryZoneName(zoneName: "Within Klang Valley")],
qrCode: "1004")]
I wanted to do price sorting from above the arrays, which the PriceOption array is store inside the main array as an object array too. How do i do sorting from PriceOption? I try to do it in this way :
for i in self.productList{
i.priceOption.sortInPlace{
$0.price.localizedCaseInsensitiveCompare($1.price) == NSComparisonResult.OrderedDescending
}
}
Which return an error "Cannot use mutating member on immutable value :'i' is a 'let' constant."
How to do this?
This how I solve issue that you present. I am using sorted method of the array class.
Solution:
self.productList.sorted{ Float($0.priceOption.first!.price)! > Float($1.priceOption.first!.price)! }
Try this
for i in self.productList {
i.priceOption.sort { $0.price < $1.price } }
The answer for swift 3 is as following
Ascending:
self.productList = self.productList.sorted(by:
{(first: ProductDetails, second: ProductDetails) -> Bool in
first.price > second.price
}
)
Descending:
self.productList = self.productList.sorted(by:
{(first: ProductDetails, second: ProductDetails) -> Bool in
first.price > second.price
}
)

Resources