I have array of objects where i need to an key value
useState :
const [row, setRow] = useState([{ nameofthework: "", schedulerefNo: "", unitprice: "", qty: "", uom: "", gst: "", total: "" }]);
The form input change function
const handleInputChange = (e, index) => {
const { name, value } = e.target;
const list = [...row];
list[index][name] = value;
setRow(list);
console.log(row); // Prints out the each row object into and array of objects
};
const handleQty = (e) => {
const scheduleNumberForQuantity = e.target.value;
projectScheduleNumber?.filter((v) => {
if(v["Schedule No"] === scheduleNumberForQuantity ) {
setScheduleQuantity(v["LOA Qty"]); // return only integer example 1000
}
})
}
How to add handleQty value to row state ?
I think that you need declare the state like a function instead of array of objects key value. It will allow setRow to be managed as function in any moment inside of the function component.
const [row, setRow] = useState<any>();
With <any> allows save anything. So you could apply a strong type like:
const [row, setRow] = useState<()=>void>();
or in you case
const [row, setRow] = useState<(e: any)=>void>();
I hope it is useful for you.
Related
What im trying to do is to not change the key of an item inside an array when the value is changed.
So basically the user can update, delete or add a new language.
To notice it In my code, I will have to add a key "added" (which means is a language added by the user when he created the account.)
When the user adds a new language the array will look like this:
language:
[
{
added: "English"
},
"Italian" //the new language add by user when edit
]
parent.js
const [language, setLanguage] = useState([])
useEffect(() => {
axios
.get('api').then((response) => {
response.data.user.map((user) => {setLanguage([...language,{added:user.language)}))
}, [])
child.js
export default function child({language, setLanguage}) {
const handleAddClick = () => {
setLanguage([...language, ""]);
};
const handleItemChanged = (event, index) => {
const value = event.target.value;
const list = [...language];
console.log("list: ", list);
list[index] = value;
setLanguage(list);
};
}
So the problem is when the user updates the language that has the key added, the key will disappear, and the array will look like this:
language:
[
"Englishhh", //updated
"Italian"
]
So I wanted the result like this:
language
[
{
added: "Englishhh" //updated
},
"Italian"
]
How can I solve it?
Did you try this way before setting the language in handleItemChanged?
if(typeof list[index] !== 'string'){
list[index].added ? list[index].added = value : list[index].language = value;
}else{
list[index] = value;
}
I'm trying to save objects to an array, but I can't do it, the old state is deleted. I have two states in my component, from two different forms, the first form is just text and I get the data by "handleChange", but the second form is several objects that I want to store in an array that I get by "handleChangeArray".
const [formCompra, setFormCompra] = useState({
name: '',
lastName: '',
items: []
});
const [restForm, setRestForm] = useState();
const handleChage = (e) => {
const { name, value } = e.target;
setFormCompra({
...formCompra,
[name]: value
})
}
const handleChangeArray = (e) => {
const { name, value } = e.target;
setRestForm({
...restForm,
[name]: value
})
}
const handleSubmit = () => {
let newData = {
name: formCompra.name,
lastName: formCompra.lastName,
items: [...formCompra.items, restForm] //probably the error is here
}
console.log(newData)
}
As I mention, it is not possible to save the data in the array, I appreciate any help.
You can use the current state to set a new value, keeping all other values:
setState((current) => ({
...current,
key: newValue
}));
I think the issue may be that spread syntax only shallow copies the array, so in
const handleSubmit = () => {
let newData = {
name: formCompra.name,
lastName: formCompra.lastName,
items: [...formCompra.items, restForm] //probably the error is here
}
items is a copy of an array that points to all the original objects.
try
let newData = {
name: formCompra.name,
lastName: formCompra.lastName,
items: [...formCompra.map(x=>{...x}), {...restForm}] //probably the error is here
}
I'm using React js. I want to add an option to delete multiple items. but after deleting each item, page refreshes the props and not delete remaining items.
How can I delete Multiple items?
const onDeleteAll = arr => {
arr.forEach(element => {
const formData = {
id:element
}
props.onDeleteSubmit(formData, function(){ // pass id to delete func
console.log('deleted')
})
});
}
useEffect(() => {
props.getPriceType(); // fetching data
}, []);
reducer:
case DELETE_PRICE_TYPE_SUCCESS_ACTION:
const myDeletedArray = draft.list;
const objDeletedIndex = myDeletedArray.filter(obj => obj.id !== action.payload._id);
draft.list = objDeletedIndex; //update data
break;
var id = 23;
var list = [{
id: 23,
value: "JOHN"
}, {
id: 23,
value: "JADE"
}, {
id: 24,
value: "JADE"
}, {
id: 25,
value: "JAMES"
}];
var indexes = [];
const templist = list.filter((item, ind) => {
return item.id !== id
});
list = templist;
console.log(list);
First get the list of indexes which matches the items in the array to be deleted. Traverse the above list and delete the items from each array by splice operator.
I think the problem is that you have multiple items to delete, but you trigger a delete action for only 1 at a time. You need to collect all the ids to delete in a list, and send that list to the action, and in reducer just filter that ids.
const onDeleteAll = arr => {
//this just to follow your current shape of things
//ideally you don't want to do that, just pass arr to the onDeleteSubmit
const formData = arr.map(element => ({
id:element
}));
props.onDeleteSubmit(formData, function(){
console.log('deleted')
})
}
useEffect(() => {
props.getPriceType(); // fetching data
}, []);
reducer:
case DELETE_PRICE_TYPE_SUCCESS_ACTION:
const myDeletedArray = draft.list;
const objDeletedIndex = myDeletedArray.filter(obj =>
!action.payload.find(itemToDelete=>itemToDelete._id===obj.id)
);
draft.list = objDeletedIndex; //update data
break;
const fields = ['email', 'password'];
const objFields = {};
fields.forEach(value => {
objFields[value] = '';
});
console.log(objFields);
// Outputs {email: "", password: ""}
I want to achieve the same result but without having to initialize an empty object.
Actually my case is that I want to set initial state of a React component.
class App extends Component {
fields = ['email', 'password'];
state = {
fields: // the one liner code here that should return the object created from fields array,
};
...
expected result would be
// state = {fields: {email: "", password: ""}}
Whenever you're looking for reducing an array of values to one value, you're looking for .reduce()
state = {
fields: fields.reduce((acc, key) => ({...acc, [key]: ''}), {}),
};
You could map objects and assign all to a single object.
const
fields = ['email', 'password'],
object = Object.assign({}, ...fields.map(key => ({ [key]: '' })));
console.log(object);
In modern browsers, or by using polyfills, you can use Object.fromEntries() to create an object from an array, using the array's values as keys/properties, and fill the object's values with a default.
const fields = ['email', 'password'];
const result = Object.fromEntries(fields.map(value => [value, '']));
The result is {email: "", password: ""}.
You need to transform your array which contains keys into a real object.
To do it you have many possibilites, but you still have to do something, there is no magical trick.
My favorite soluce is to use a function to insert into your Utilitary class. So it's easy to read and re-usable.
number 1 : The function
function initializeKeys(keys, initialValue, object) {
return keys.reduce((tmp, x) => {
tmp[x] = initialValue;
return tmp;
}, object);
}
const objFields = initializeKeys(['email', 'password'], '', {
otherKey: 'a',
});
console.log(objFields);
number 2 : The forEach
const fields = ['email', 'password'];
const objFields = {};
fields.forEach(value => {
objFields[value] = '';
});
console.log(objFields);
number 3 : The reduce
const fields = ['email', 'password'];
const objFields = {
...fields.reduce((tmp, x) => {
tmp[x] = '';
return tmp;
}, {}),
};
console.log(objFields);
I need to add an id number to the nested array in data called action. The code I'm using is:
const { data } = this.state
const newData = Object.assign([...data.action], Object.assign([...data.action],{0:'id' }))
but this code is not working. The result I am looking for is:
{id:1 action: "user...}
You can just use the spread operator.
const newData = {
...data,
action: {
...data.action,
id: 1
}
};
If action is an array, you can try something like this:
const newAction = data.action.map((actionItem, index) => ({
...actionItem,
id: index + 1
}));
const newData = {
...data,
action: newAction
};